blob: 95421e5bf610a3c52d48dd262fd976bceed48035 [file] [log] [blame]
/*****************************************************************************
*
* Filename:
* ---------
* custom_sml.c
*
* Project:
* --------
* UMOLYA
*
* Description:
* ------------
* This file is for SIM ME Lock customization
*
* Author:
* -------
* -------
****************************************************************************/
#if !defined(__MAUI_BASIC__)
#include <string.h>
#include "kal_general_types.h"
#include "kal_public_api.h"
#include "global_def.h"
#include "custom_sml.h"
#include "custom_sml_trc.h"
#include "custom_nvram_extra.h"
#include "ps_public_enum.h"
#include "sim_ps_enum.h"
#include "smu_common_enums.h"
#include "mcd_l3_inc_struct.h"
#include "nvram_interface.h"
#include "cust_chl_interface.h"
#include "custom_sml_sec_verify.h"
#include "l4c_utility.h"
#include "ps_public_utility.h"
extern void smu_nvram_write(nvram_lid_enum file_idx, kal_uint8 access_id, kal_bool is_write_protect2);
#ifndef L4_NOT_PRESENT
/****************************************************************************
*
* SIM ME Lock
*
****************************************************************************/
#ifdef __CUST_SML_RULE__
const kal_uint8 sml_gblob_max_cust_rule[SML_LOCK_CUST_CODE_SIZE + 1] = SML_GBLOB_MAX_CUST_RULE_LIST;
#endif
/*******************************************************************************
* FUNCTION
* sml_mini_trace
* DESCRIPTION
* trace for short strings
* PARAMETERS
* title [const kal_char]
* data [kal_uint8]
* len [kal_uint8]
* RETURN
* void
*******************************************************************************/
void sml_mini_trace(const kal_char *title, kal_uint8 *data, kal_uint8 len)
{
kal_uint8 *buf = NULL;
kal_uint8 buf_len = (len < 128 ? len : 128);
buf = get_ctrl_buffer(128 + 1);
kal_mem_set(buf, 0, 128 + 1);
kal_mem_cpy(buf, data, buf_len);
kal_prompt_trace(kal_get_active_module_id(), "%s: ", title);
kal_prompt_trace(kal_get_active_module_id(), "%s", (const kal_char *)buf);
}
/*******************************************************************************
* FUNCTION
* custom_sml_query_key_input_type
* DESCRIPTION
* This function is to query under particular protection algorithm and operation pair,
* whether our key input is plaintext key (e.g. '123456') or hashed key (e.g. {0xAA, 0xBB, ...})
* PARAMETERS
* algo key protection algorithm
* op operation for querying key input type
* RETURN
* SML_VERIFY_WITH_PLAINKEY: Input is plaintext key, may need to derive its hashed value for verification
* SML_VERIFY_WITH_HCK: Input is hashed key, directly compare its stored hashed value for verification
* GLOBALS AFFECTED
* N/A
*******************************************************************************/
sml_key_input_type_enum custom_sml_query_key_input_type(sml_key_algo_enum algo, sml_op_enum op)
{
sml_key_input_type_enum input_type = SML_INPUT_WITH_PLAINKEY;
if (algo == SML_KEY_ALGO_BCD) /* algo == 0 */
{
input_type = SML_INPUT_WITH_PLAINKEY;
}
else if (algo == SML_KEY_ALGO_PBKDF2_HMAC_SHA256_SALT128) /* algo == 1 */
{
switch (op)
{
case SML_OP_VERIFY:
case SML_OP_CHANGE_PWD:
input_type = SML_INPUT_WITH_PLAINKEY;
break;
case SML_OP_UNLOCK:
case SML_OP_LOCK:
case SML_OP_ADD:
case SML_OP_REMOVE:
case SML_OP_DISABLE:
case SML_OP_UPDATE_AUTOLOCK_COUNT:
input_type = SML_INPUT_WITH_HCK;
break;
default:
break;
}
}
return input_type;
}
#ifdef __SML_PUK__
/*******************************************************************************
* FUNCTION
* custom_sml_query_puk_key_input_type
* DESCRIPTION
* This function is to query under particular protection algorithm and operation pair,
* whether our key input is plaintext key (e.g. '123456') or hashed key (e.g. {0xAA, 0xBB, ...})
* PARAMETERS
* algo key protection algorithm
* op operation for querying key input type
* RETURN
* SML_VERIFY_WITH_PLAINKEY: Input is plaintext key, may need to derive its hashed value for verification
* SML_VERIFY_WITH_HCK: Input is hashed key, directly compare its stored hashed value for verification
* GLOBALS AFFECTED
* N/A
*******************************************************************************/
sml_key_input_type_enum custom_sml_query_puk_key_input_type(sml_key_algo_enum algo, sml_puk_key_op_enum op)
{
sml_key_input_type_enum input_type = SML_INPUT_WITH_PLAINKEY;
if (algo == SML_KEY_ALGO_BCD) /* algo == 0 */
{
input_type = SML_INPUT_WITH_PLAINKEY; // Only PLAINTEXT allowed
}
else if (algo == SML_KEY_ALGO_PBKDF2_HMAC_SHA256_SALT128) /* algo == 1 */
{
switch (op)
{
case SML_PUK_OP_VERIFY:
input_type = SML_INPUT_WITH_PLAINKEY;
break;
case SML_PUK_OP_UPDATE:
input_type = SML_INPUT_WITH_HCK;
break;
default:
break;
}
}
return input_type;
}
#endif /* __SML_PUK__ */
/****************************************************************************
*
* Verizon SIM Lock
*
****************************************************************************/
/* define the Local variable of VZW SML object */
static sml_vzw_sim_lock_context_struct sml_vzw_cntxt_obj[MAX_SIM_NUM];
static nvram_ef_sml_vzw_sim_lock_obj_struct SMLVZWOBJ[MAX_SIM_NUM];
/* define the Global access pointer of VZW SML object */
nvram_ef_sml_vzw_sim_lock_obj_struct * pSMLVZWg = &SMLVZWOBJ[0];
/*******************************************************************************
* FUNCTION
* sml_clean_vzw_cntxt
* DESCRIPTION
* Clean sensitive data in MD Dump.
* PARAMETERS
* N/A
* RETURN
* N/A
* GLOBALS AFFECTED
* sml_vzw_cntxt_obj
*******************************************************************************/
void sml_clean_vzw_cntxt(void)
{
kal_mem_set(sml_vzw_cntxt_obj, 0x00, sizeof(sml_vzw_cntxt_obj));
}
/*******************************************************************************
* FUNCTION
* custom_sml_vzw_is_test_purpose
* DESCRIPTION
* This function is to query if VzW testing functions are enabled
* PARAMETERS
* N/A
* RETURN
* KAL_TRUE: For test purpose, testing function enabled
* KAL_FALSE: Normal purpose
* GLOBALS AFFECTED
* N/A
*******************************************************************************/
kal_bool custom_sml_vzw_is_test_purpose(void)
{
#ifdef __VZW_RSU_TEST__
return KAL_TRUE;
#else
return KAL_FALSE;
#endif
}
/*******************************************************************************
* FUNCTION
* sml_vzw_give
* DESCRIPTION
* This method copys the LID files read from NVRAM to the SML obj
* PARAMETERS
* IN * pLidToObj
* RETURN
* void
* GLOBALS AFFECTED
* SMLOBJ
*******************************************************************************/
void sml_vzw_give(void *pLidToObj, kal_uint8 source)
{
sml_vzw_sim_lock_context_struct * pObj = NULL;
if(NULL != pSMLVZWg[source].pObj)
{
pSMLVZWg[source].pObj = NULL;
}
pObj = &(sml_vzw_cntxt_obj[source]);
kal_mem_cpy(pObj,
pLidToObj,
sizeof(sml_vzw_sim_lock_context_struct)
);
pSMLVZWg[source].pObj = pObj;
}
/*******************************************************************************
* FUNCTION
* sml_vzw_take
* DESCRIPTION
* This method copys the contex of the SML object to the provided NVRAM LID.
* PARAMETERS
* OUT * pObjToLid
* RETURN
* void
* GLOBALS AFFECTED
* SMLOBJ
*******************************************************************************/
void sml_vzw_take( void *pObjToLid, kal_uint8 source )
{
sml_vzw_sim_lock_context_struct * pObj = (sml_vzw_sim_lock_context_struct *) pSMLVZWg[source].pObj;
kal_mem_cpy(pObjToLid,
pObj,
sizeof(sml_vzw_sim_lock_context_struct)
);
}
/*******************************************************************************
* FUNCTION
* sml_vzw_destory
* DESCRIPTION
* This method free the SML object in memory if it is not used.
* PARAMETERS
* void
* RETURN
* void
* GLOBALS AFFECTED
* SMLOBJ
*******************************************************************************/
void sml_vzw_destory(kal_uint8 source)
{
pSMLVZWg[source].pObj = NULL;
}
/*******************************************************************************
* FUNCTION
* sml_vzw_Load
* DESCRIPTION
* This function loads the SML obj from NVRAM LID (NVRAM_READ_CNF)
* PARAMETERS
* IN pLid
* RETURN
* kal_uint16 Obj size
* GLOBALS AFFECTED
* SMLOBJ
*******************************************************************************/
kal_uint16 sml_vzw_Load( void *pLid, kal_uint8 source )
{
nvram_ef_sml_vzw_sim_lock_obj_struct *p = &pSMLVZWg[source];
kal_uint16 length = sizeof(sml_vzw_sim_lock_context_struct);
/* Clean the old ones */
(*p->destory)(source);
/* Load the new one */
(*p->give)(pLid, source);
return length;
}
/*******************************************************************************
* FUNCTION
* sml_vzw_Save
* DESCRIPTION
* This function saves the SML obj to NVRAM LID (NVRAM_WRITE_REQ)
* PARAMETERS
* OUT pLid
* RETURN
* kal_uint16 Obj size
* GLOBALS AFFECTED
* SMLOBJ
*******************************************************************************/
kal_uint16 sml_vzw_Save( void *pLid, kal_uint8 source )
{
nvram_ef_sml_vzw_sim_lock_obj_struct *p = &pSMLVZWg[source];
kal_uint16 length = sizeof(sml_vzw_sim_lock_context_struct);
kal_uint8 lock_state = SML_VZW_LOCK_STATE_LOCK;
kal_bool ret_val = KAL_FALSE;
kal_bool temp_unlock_restore_required = KAL_FALSE;
/* Check if NW lock op is set to Temp unlock in SML VzW OBJ. If yes, then change it to Lock before performing 'take' operation.
Then restore back to Temp unlock after 'take' operation */
ret_val = sml_vzw_get_int_data(source, SML_VZW_CAT_NONE, SML_VZW_RSU_NETWORK_LOCK_OPERATION, &lock_state);
if (KAL_FALSE == ret_val)
{
DEBUG_ASSERT(0);
}
else
{
if (lock_state == SML_VZW_LOCK_STATE_TEMP_UNLOCK)
{
ret_val = sml_vzw_update_int_data(source, SML_VZW_CAT_NONE, SML_VZW_RSU_NETWORK_LOCK_OPERATION, SML_VZW_LOCK_STATE_LOCK);
if (ret_val == KAL_TRUE)
{
temp_unlock_restore_required = KAL_TRUE;
}
}
}
(*p->take)(pLid, source);
if (KAL_TRUE == temp_unlock_restore_required)
{
sml_vzw_update_int_data(source, SML_VZW_CAT_NONE, SML_VZW_RSU_NETWORK_LOCK_OPERATION, SML_VZW_LOCK_STATE_TEMP_UNLOCK);
}
return length;
}
/*******************************************************************************
* FUNCTION
* sml_vzw_getItem
* DESCRIPTION
* This method returns the structure pointer and length of the structure
* of the desired SML object items.
* PARAMETERS
* IN cat
* IN item
* OUT *length
* RETURN
* void *
* GLOBALS AFFECTED
* SMLOBJ
*******************************************************************************/
void * sml_vzw_getItem(sml_vzw_cat_enum category,
sml_ctx_enum item,
kal_uint16 *plength,
kal_uint8 source)
{
sml_vzw_sim_lock_context_struct *pObj = (sml_vzw_sim_lock_context_struct *) pSMLVZWg[source].pObj;
ASSERT(NULL != pObj);
switch(item)
{
case SML_VZW_RSU_MAJOR_VERSION:
*plength = sizeof(kal_uint8);
return (kal_uint8 *) &(pObj->major_version);
case SML_VZW_RSU_MINOR_VERSION:
*plength = sizeof(kal_uint8);
return (kal_uint8 *) &(pObj->minor_version);
case SML_VZW_RSU_PROTECTION_ALGORITHM:
*plength = sizeof(kal_uint8);
return (kal_uint8 *) &(pObj->protection_algo);
case SML_VZW_RSU_NETWORK_LOCK_OPERATION:
*plength = sizeof(kal_uint8);
return (kal_uint8 *) &(pObj->nw_lock_op);
case SML_VZW_RSU_TIME_STAMP:
*plength = SML_VZW_RSU_TIME_STAMP_LEN;
return (kal_uint8 *) &(pObj->timestamp[0]);
case SML_VZW_RSU_SESSION_ID:
*plength = SML_VZW_RSU_SESSION_ID_LEN;
return (kal_uint8 *) &(pObj->session_id[0]);
case SML_VZW_RSU_CAT_CODE:
switch(category)
{
case SML_VZW_CAT_N:
*plength = SML_VZW_RSU_NW_LIST_LEN;
return (kal_uint8 *) &(pObj->nw_list[0]);
break;
case SML_VZW_CAT_NS:
*plength = SML_VZW_RSU_NS_LIST_LEN;
return (kal_uint8 *) &(pObj->ns_list[0]);
break;
case SML_VZW_CAT_SP:
*plength = SML_VZW_RSU_SP_LIST_LEN;
return (kal_uint8 *) &(pObj->sp_list[0]);
break;
case SML_VZW_CAT_EHPLMN:
*plength = SML_VZW_RSU_EHPLMN_LIST_LEN;
return (kal_uint8 *) &(pObj->ehplmn_list[0]);
break;
default:
/* do nothing */
break;
}
break;
case SML_VZW_RSU_CAT_NUM:
switch(category)
{
case SML_VZW_CAT_N:
*plength = sizeof(kal_uint8);
return (kal_uint8 *) &(pObj->nw_num);
break;
case SML_VZW_CAT_NS:
*plength = sizeof(kal_uint8);
return (kal_uint8 *) &(pObj->ns_num);
break;
case SML_VZW_CAT_SP:
*plength = sizeof(kal_uint8);
return (kal_uint8 *) &(pObj->sp_num);
break;
case SML_VZW_CAT_EHPLMN:
*plength = sizeof(kal_uint8);
return (kal_uint8 *) &(pObj->ehplmn_num);
break;
default:
/* do nothing */
break;
}
break;
default:
break;
}
return NULL;
}
/*******************************************************************************
* FUNCTION
* sml_vzw_putItem
* DESCRIPTION
* This method set the desired items of the SML object.
* PARAMETERS
* IN cat
* IN item
* IN *pItem
* IN *plength
* RETURN
* void
* GLOBALS AFFECTED
* SMLOBJ
*******************************************************************************/
void sml_vzw_putItem(sml_vzw_cat_enum cat,
sml_ctx_enum item,
void *pItem,
kal_uint16 *plength,
kal_uint8 source)
{
sml_vzw_sim_lock_context_struct *pObj = (sml_vzw_sim_lock_context_struct *) pSMLVZWg[source].pObj;
switch (item)
{
case SML_VZW_RSU_MAJOR_VERSION:
kal_mem_cpy(&(pObj->major_version), pItem, *plength);
break;
case SML_VZW_RSU_MINOR_VERSION:
kal_mem_cpy(&(pObj->minor_version), pItem, *plength);
break;
case SML_VZW_RSU_PROTECTION_ALGORITHM:
kal_mem_cpy(&(pObj->protection_algo), pItem, *plength);
break;
case SML_VZW_RSU_NETWORK_LOCK_OPERATION:
kal_mem_cpy(&(pObj->nw_lock_op), pItem, *plength);
break;
case SML_VZW_RSU_SESSION_ID:
kal_mem_cpy(pObj->session_id, pItem, *plength);
break;
case SML_VZW_RSU_TIME_STAMP:
kal_mem_cpy(pObj->timestamp, pItem, *plength);
break;
case SML_VZW_RSU_CAT_CODE:
switch(cat)
{
case SML_VZW_CAT_N:
kal_mem_cpy(pObj->nw_list, pItem, *plength);
break;
case SML_VZW_CAT_NS:
kal_mem_cpy(pObj->ns_list, pItem, *plength);
break;
case SML_VZW_CAT_SP:
kal_mem_cpy(pObj->sp_list, pItem, *plength);
break;
case SML_VZW_CAT_EHPLMN:
kal_mem_cpy(pObj->ehplmn_list, pItem, *plength);
break;
default:
/* do nothing */
break;
}
break;
case SML_VZW_RSU_CAT_NUM:
switch(cat)
{
case SML_VZW_CAT_N:
kal_mem_cpy(&(pObj->nw_num), pItem, *plength);
break;
case SML_VZW_CAT_NS:
kal_mem_cpy(&(pObj->ns_num), pItem, *plength);
break;
case SML_VZW_CAT_SP:
kal_mem_cpy(&(pObj->sp_num), pItem, *plength);
break;
case SML_VZW_CAT_EHPLMN:
kal_mem_cpy(&(pObj->ehplmn_num), pItem, *plength);
break;
default:
/* do nothing */
break;
}
break;
default:
break;
}
}
/*******************************************************************************
* FUNCTION
* sml_vzw_Catcode
* DESCRIPTION
* This function is used to compose the code of each category
* PARAMETERS
* IN cat
* IN *imsi
* IN *vzw_gid1_len
* IN *gid1
* IN *ehplmn
* IN mnc_len
* OUT *code
* RETURN
* kal_uint8 code length
* GLOBALS AFFECTED
* NONE
*******************************************************************************/
kal_uint8 sml_vzw_Catcode( sml_vzw_cat_enum cat,
kal_uint8 *imsi,
kal_uint8 vzw_gid1_len,
kal_uint8 *gid1,
kal_uint8 *ehplmn,
kal_uint8 mnc_len,
kal_uint8 *code )
{
kal_uint8 i = 0;
kal_uint8 gid1_start_pos = 7;
kal_uint8 ehplmn_start_pos = (vzw_gid1_len < NUM_GID1)? (gid1_start_pos + vzw_gid1_len) : (gid1_start_pos + NUM_GID1);
if (imsi == NULL)
{
return 0;
}
if(mnc_len == 3)
{
/* MCC/MNC */
code[0] = ((imsi[1]&0xF0)>>4) + '0';
code[1] = (imsi[2]&0x0F) + '0';
code[2] = ((imsi[2]&0xF0)>>4) + '0';
code[3] = (imsi[3]&0x0F) + '0';
code[4] = ((imsi[3]&0xF0)>>4) + '0';
code[5] = (imsi[4]&0x0F) + '0';
code[6] = ((imsi[4]&0xF0)>>4) + '0';
code[7] = (imsi[5]&0x0F) + '0';
}
else
{
/* MCC/MNC */
code[0] = ((imsi[1]&0xF0)>>4) + '0';
code[1] = (imsi[2]&0x0F) + '0';
code[2] = ((imsi[2]&0xF0)>>4) + '0';
code[3] = (imsi[3]&0x0F) + '0';
code[4] = ((imsi[3]&0xF0)>>4) + '0';
code[5] = 'F';
code[6] = (imsi[4]&0x0F) + '0';
code[7] = ((imsi[4]&0xF0)>>4) + '0';
}
switch(cat)
{
case SML_VZW_CAT_N:
return SML_VZW_RSU_NW_CODE_LEN;
break;
case SML_VZW_CAT_NS:
return SML_VZW_RSU_NS_CODE_LEN;
break;
case SML_VZW_CAT_SP:
if (NULL != gid1)
{
code[6] = vzw_gid1_len;
/* GID */
for (i = 0; (i < vzw_gid1_len) && (i < NUM_GID1); i++)
{
code[gid1_start_pos+i] = gid1[i];
}
return gid1_start_pos + i;
}
else
{
return 0;
}
break;
case SML_VZW_CAT_EHPLMN:
if (NULL != gid1)
{
code[6] = vzw_gid1_len;
/* Verizon use 8 bytes of GID1 */
for (i = 0; (i < vzw_gid1_len) && (i < NUM_GID1); i++)
{
code[gid1_start_pos+i] = gid1[i];
}
}
else
{
return 0;
}
if (ehplmn != NULL)
{
if (*ehplmn == 0xff)
{
return 0;
}
else
{
/* EHPLMN format is :
MCC2|MCC1 MNC3(opt)|MCC3 MNC2|MNC1
*/
code[ehplmn_start_pos] = (ehplmn[0]&0x0F) + '0'; //MCC1
code[ehplmn_start_pos+1] = ((ehplmn[0]&0xF0)>>4) + '0'; //MCC2
code[ehplmn_start_pos+2] = (ehplmn[1]&0x0F) + '0'; //MCC3
code[ehplmn_start_pos+3] = (ehplmn[2]&0x0F) + '0'; //MNC1
code[ehplmn_start_pos+4] = ((ehplmn[2]&0xF0)>>4) + '0'; //MNC2
if ((ehplmn[1] & 0xF0) == 0xF0) //this EHPLMN mnc len = 2
{
code[ehplmn_start_pos+5] = 0xFF;
}
else
{
code[ehplmn_start_pos+5] = ((ehplmn[1] & 0xF0)>>4) + '0'; //MNC3
}
return ehplmn_start_pos + 6;
}
}
else
{
return 0;
}
break;
default:
break;
}
return 0;
}
/*******************************************************************************
* FUNCTION
* sml_vzw_GetCode
* DESCRIPTION
* This function is used to compose the code of each category whether
* mnc length is 2 or 3
* PARAMETERS
* cat [IN] category of the SIM-ME-Lock
* imsi [IN] imsi of the code source
* vzw_gid1_len [IN] gid1 lengh from VZW code
* gid1 [IN] gid1 of the code source
* sim_mnc_len [IN] the mnc length decided by SIM
* pdata [IN] the saved code for comparing
* pdata_len [IN] the length of saved code for comparing
* code [OUT] the composed code according to all input parameters
*
* RETURN
* kal_uint16 file size
* GLOBALS AFFECTED
* SMLSLOBJ
*******************************************************************************/
kal_uint8 sml_vzw_GetCode( sml_vzw_cat_enum cat,
kal_uint8 *imsi,
kal_uint8 vzw_gid1_len,
kal_uint8 *gid1,
kal_uint8 *ehplmn,
kal_uint8 sim_mnc_len,
kal_uint8 *pdata,
kal_uint8 *pdata_len,
kal_uint8 *code)
{
kal_uint8 mnc_len=0;
if (SML_MNC_LENGTH_NEST == 1)
{
mnc_len = sim_mnc_len;
}
else
{
if (((*(pdata+5)) == 'F') || ((*(pdata+5)) == 'f'))
{
mnc_len = 2;
*(pdata+5) = 'F';
}
else
{
mnc_len = 3;
}
}
switch (cat)
{
case SML_VZW_CAT_N:
*pdata_len = SML_VZW_RSU_NW_CODE_LEN;
break;
case SML_VZW_CAT_NS:
*pdata_len = SML_VZW_RSU_NS_CODE_LEN;
break;
case SML_VZW_CAT_SP:
*pdata_len = SML_VZW_RSU_NW_CODE_LEN + 1 + vzw_gid1_len;
break;
case SML_VZW_CAT_EHPLMN:
*pdata_len = (SML_VZW_RSU_NW_CODE_LEN*2) + 1 + vzw_gid1_len;
break;
default:
DEBUG_ASSERT(0);
*pdata_len = 0;
}
return sml_vzw_Catcode(cat, imsi, vzw_gid1_len, gid1, ehplmn, mnc_len, code);
}
/*******************************************************************************
* FUNCTION
* sml_vzw_Check
* DESCRIPTION
* This function is used to check if the code is in the Pass list
* PARAMETERS
* IN cat
* IN *imsi
* IN *gid1
* IN ehplmn_num
* IN *ehplmn_ptr
* IN len
* IN source
* RETURN
* kal_bool
* GLOBALS AFFECTED
* SMLOBJ
*******************************************************************************/
kal_bool sml_vzw_Check( sml_vzw_cat_enum cat,
kal_uint8 *imsi,
kal_uint8 *gid1,
kal_uint16 ehplmn_num,
kal_uint8 *ehplmn_ptr,
kal_uint8 sim_mnc_len,
kal_uint8 source)
{
nvram_ef_sml_vzw_sim_lock_obj_struct *p = &pSMLVZWg[source];
kal_uint8 *num_list = NULL;
kal_uint8 *list_data = NULL;
kal_uint8 *vzw_code_ptr = NULL;
kal_uint8 vzw_code_len = 0;
kal_uint16 length = 0;
kal_uint8 code[SML_VZW_RSU_EHPLMN_CODE_LEN] = {0}; //use ehplmn code len as max code len
kal_uint8 code_len = 0;
kal_uint8 vzw_gid1_len;
kal_uint16 i = 0;
kal_uint8 code_dbg_str[(SML_VZW_RSU_EHPLMN_CODE_LEN)*3 + 1] = {0};
kal_uint8 iter = 1; //iteration for EHPLMN Configuration, limited by MD1_MAX_NUM_HPLMN
/* Check the integration of SIM Lock blob first */
if (p->pObj== NULL)
{
MD_TRC_WARNING_SML_CHECK_VALIDITY_FAILED();
}
else
{
num_list = (kal_uint8 *)(*p->getItem)(cat, SML_VZW_RSU_CAT_NUM, &length, source);
if (*num_list == 0)
{
// TODO: list is empty, always pass or blocked? currently is pass
return KAL_TRUE;
}
else
{
list_data = (kal_uint8 *)(*p->getItem)(cat, SML_VZW_RSU_CAT_CODE, &length, source);
vzw_code_ptr = list_data;
}
for (i = 0; i < *num_list; i++)
{
kal_uint8 *temp_ehplmn_ptr = ehplmn_ptr;
if (SML_VZW_CAT_EHPLMN == cat)
{
iter = (ehplmn_num < MD1_MAX_NUM_HPLMN)? ehplmn_num : MD1_MAX_NUM_HPLMN;
}
else
{
iter = 1;
}
if ((SML_VZW_CAT_SP == cat) || (SML_VZW_CAT_EHPLMN == cat))
{
vzw_gid1_len = vzw_code_ptr[6];
}
else
{
vzw_gid1_len = 0;
}
while (iter > 0)
{
kal_uint8 j = 0, k = 0;
iter--;
code_len = sml_vzw_GetCode(cat, imsi, vzw_gid1_len, gid1, temp_ehplmn_ptr, sim_mnc_len, vzw_code_ptr, &vzw_code_len, code);
if (iter >= 1)
{
temp_ehplmn_ptr += 3; //for next iteration if more than one EHPLMN from SIM
}
while ((j < code_len) && (k <= (sizeof(code_dbg_str) - 4)))
{
kal_int8 temp_len;
temp_len = kal_sprintf((kal_char*)code_dbg_str + k, "%02x ", code[j]);
if (temp_len <= 0)
{
kal_mem_cpy(code_dbg_str + k, "ERR", sizeof("ERR"));
k += 3;
break;
}
k += temp_len;
j++;
}
code_dbg_str[k] = '\0';
MD_TRC_INFO_SMU_CHECK_LENGTH(code_len, vzw_code_len, sim_mnc_len);
MD_TRC_INFO_SML_VZW_CODE_DEBUG((kal_char*)code_dbg_str);
/* we support dynamic comparing code length by using the code_len in stead of fixed length.
After that, vzw_code_ptr will shift according to each individual code length.
In addition, the VZW SIM Lock NVRAM structure is defined as max size.
*/
if ((code_len > 0) && (kal_mem_cmp(code, vzw_code_ptr, code_len) == 0))
{
return KAL_TRUE;
}
kal_mem_set(code, 0, SML_VZW_RSU_EHPLMN_CODE_LEN);
}
//shift to next code of the compared category
vzw_code_ptr += vzw_code_len;
}
}
return KAL_FALSE;
}
kal_bool sml_vzw_update_int_data(kal_uint8 source, sml_vzw_cat_enum cat, sml_ctx_enum type, kal_uint8 data)
{
nvram_ef_sml_vzw_sim_lock_obj_struct *p = &pSMLVZWg[source];
kal_uint16 length = sizeof(kal_uint8);
/* Check the integration of SIM Lock blob first */
if (p->pObj == NULL)
{
MD_TRC_WARNING_SML_CHECK_VALIDITY_FAILED();
return KAL_FALSE;
}
(*p->putItem)(cat, type, &data, &length, source);
return KAL_TRUE;
}
kal_bool sml_vzw_get_int_data(kal_uint8 source, sml_vzw_cat_enum cat, sml_ctx_enum type, kal_uint8* pData)
{
nvram_ef_sml_vzw_sim_lock_obj_struct *p = &pSMLVZWg[source];
kal_uint16 length;
kal_bool ret_val = KAL_FALSE;
/* Check the integration of SIM Lock blob first */
if (p->pObj == NULL)
{
MD_TRC_WARNING_SML_CHECK_VALIDITY_FAILED();
}
else
{
*pData = *((kal_uint8 *)(*p->getItem)(cat, type, &length, source));
if (length == sizeof(kal_uint8))
{
ret_val = KAL_TRUE;
}
else
{
MD_TRC_WARNING_SML_VZW_RSU_GET_INT_DATA_FAILED(cat, type);
}
}
return ret_val;
}
kal_bool sml_vzw_update_array_data(kal_uint8 source, sml_vzw_cat_enum cat, sml_ctx_enum type, kal_uint8* data, kal_uint16 data_len)
{
nvram_ef_sml_vzw_sim_lock_obj_struct *p = &pSMLVZWg[source];
/* Check the integration of SIM Lock blob first */
if (p->pObj == NULL)
{
MD_TRC_WARNING_SML_CHECK_VALIDITY_FAILED();
return KAL_FALSE;
}
(*p->putItem)(cat, type, data, &data_len, source);
return KAL_TRUE;
}
kal_bool sml_vzw_get_array_data(kal_uint8 source, sml_vzw_cat_enum cat, sml_ctx_enum type, kal_uint8* data, kal_uint16* data_len)
{
nvram_ef_sml_vzw_sim_lock_obj_struct *p = &pSMLVZWg[source];
kal_uint8* pData = NULL;
/* Check the integration of SIM Lock blob first */
if (p->pObj == NULL)
{
MD_TRC_WARNING_SML_CHECK_VALIDITY_FAILED();
return KAL_FALSE;
}
pData = (kal_uint8 *)(*p->getItem)(cat, type, data_len, source);
kal_mem_cpy(data, pData, *data_len);
return KAL_TRUE;
}
kal_uint8 sml_vzw_get_major_version(kal_uint8 source)
{
nvram_ef_sml_vzw_sim_lock_obj_struct *p = &pSMLVZWg[source];
kal_uint8 *pMajor_ver = NULL;
kal_uint16 length = 0;
/* Check the integration of SIM Lock blob first */
if (p->pObj == NULL)
{
MD_TRC_WARNING_SML_CHECK_VALIDITY_FAILED();
return KAL_FALSE;
}
pMajor_ver = (kal_uint8 *)(*p->getItem)(SML_VZW_CAT_NONE, SML_VZW_RSU_MAJOR_VERSION, &length, source);
return *pMajor_ver;
}
kal_uint8 sml_vzw_get_max_support_major_version()
{
return SML_VZW_RSU_MAX_SUPPORT_MAJOR_VER;
}
kal_uint8 sml_vzw_get_minor_version(kal_uint8 source)
{
nvram_ef_sml_vzw_sim_lock_obj_struct *p = &pSMLVZWg[source];
kal_uint8 *pMinor_ver = NULL;
kal_uint16 length = 0;
/* Check the integration of SIM Lock blob first */
if (p->pObj == NULL)
{
MD_TRC_WARNING_SML_CHECK_VALIDITY_FAILED();
return KAL_FALSE;
}
pMinor_ver = (kal_uint8 *)(*p->getItem)(SML_VZW_CAT_NONE, SML_VZW_RSU_MINOR_VERSION, &length, source);
return *pMinor_ver;
}
kal_uint8 sml_vzw_get_max_support_minor_version()
{
return SML_VZW_RSU_MAX_SUPPORT_MINOR_VER;
}
extern const nvram_sml_vzw_sim_lock_context_struct NVRAM_EF_L4_SML_VZW_SIM_LOCK_DEFAULT;
kal_bool sml_vzw_reset_rsu_data(kal_uint8 source)
{
nvram_ef_sml_vzw_sim_lock_obj_struct* p = &pSMLVZWg[source];
sml_vzw_sim_lock_context_struct* pDefaultBlob = (sml_vzw_sim_lock_context_struct*)&NVRAM_EF_L4_SML_VZW_SIM_LOCK_DEFAULT;
/* Check the integration of SIM Lock blob first */
if (p->pObj == NULL)
{
MD_TRC_WARNING_SML_CHECK_VALIDITY_FAILED();
return KAL_FALSE;
}
// Set Network Lock
sml_vzw_update_int_data(source, SML_VZW_CAT_NONE, SML_VZW_RSU_NETWORK_LOCK_OPERATION, SML_VZW_LOCK_STATE_LOCK);
// Reset NW Configuration
sml_vzw_update_int_data(source, SML_VZW_CAT_N, SML_VZW_RSU_CAT_NUM, pDefaultBlob->nw_num);
sml_vzw_update_array_data(source, SML_VZW_CAT_N, SML_VZW_RSU_CAT_CODE, pDefaultBlob->nw_list, SML_VZW_RSU_NW_LIST_LEN);
// Reset NS Configuration
sml_vzw_update_int_data(source, SML_VZW_CAT_NS, SML_VZW_RSU_CAT_NUM, pDefaultBlob->ns_num);
sml_vzw_update_array_data(source, SML_VZW_CAT_NS, SML_VZW_RSU_CAT_CODE, pDefaultBlob->ns_list, SML_VZW_RSU_NS_LIST_LEN);
// Reset SP Configuration
sml_vzw_update_int_data(source, SML_VZW_CAT_SP, SML_VZW_RSU_CAT_NUM, pDefaultBlob->sp_num);
sml_vzw_update_array_data(source, SML_VZW_CAT_SP, SML_VZW_RSU_CAT_CODE, pDefaultBlob->sp_list, SML_VZW_RSU_SP_LIST_LEN);
// Reset EHPLMN Configuration
sml_vzw_update_int_data(source, SML_VZW_CAT_EHPLMN, SML_VZW_RSU_CAT_NUM, pDefaultBlob->ehplmn_num);
sml_vzw_update_array_data(source, SML_VZW_CAT_EHPLMN, SML_VZW_RSU_CAT_CODE, pDefaultBlob->ehplmn_list, SML_VZW_RSU_EHPLMN_LIST_LEN);
return KAL_TRUE;
}
void custom_vzw_rsu_get_pub_key_handle(kal_uint8 index, TYPE_CUST_CHL_KEY *key)
{
TYPE_CUST_CHL_KEY pub_key[] = {
CUST_VZ_PUB_KEY // index == 0, do not change this.
// Add test key handle here
};
#define VZW_KEY_SET_MAX_NUM (sizeof(pub_key)/sizeof(pub_key[0]))
index = index > (VZW_KEY_SET_MAX_NUM - 1) ? 0 : index;
if (NULL != key)
{
*key = pub_key[index];
MD_TRC_INFO_SML_RSU_PUB_KEY_HANDLE((*key));
}
return;
}
/****************************************************************************
*
* TMO SIM Lock with Movial Solution
*
****************************************************************************/
#ifdef __TMO_RSU_OTP__
static kal_bool custom_check_is_default_tmo_blob(kal_uint8 *imei);
#endif /* __TMO_RSU_OTP__ */
/* define the Local variable of TMO MOVIAL SML object */
static sml_tmo_movial_sim_lock_context_struct sml_tmo_movial_cntxt_obj[MAX_SIM_NUM];
static nvram_ef_sml_tmo_movial_sim_lock_obj_struct SMLTMMOBJ[MAX_SIM_NUM];
/* define the Global access pointer of TMO MOVIAL SML object */
nvram_ef_sml_tmo_movial_sim_lock_obj_struct* pSMLTMMg = &SMLTMMOBJ[0];
/* time to temporary unlock expiry in seconds */
kal_uint32 sml_tmo_movial_seconds_to_expire = 0;
#ifdef UNIT_TEST
kal_uint8 imei_bcd_ut[9];
#endif /* UNIT_TEST */
/*******************************************************************************
* FUNCTION
* sml_clean_tmo_movial_cntxt
* DESCRIPTION
* Clean sensitive data in MD Dump.
* PARAMETERS
* N/A
* RETURN
* N/A
* GLOBALS AFFECTED
* sml_tmo_movial_cntxt_obj
*******************************************************************************/
void sml_clean_tmo_movial_cntxt(void)
{
kal_mem_set(sml_tmo_movial_cntxt_obj, 0x00, sizeof(sml_tmo_movial_cntxt_obj));
}
/*******************************************************************************
* FUNCTION
* sml_tmo_movial_give
* DESCRIPTION
* This method copys the LID files read from NVRAM to the SML obj
* PARAMETERS
* IN * pLidToObj
* RETURN
* void
* GLOBALS AFFECTED
* SMLTMMOBJ
*******************************************************************************/
void sml_tmo_movial_give( void *pLidToObj, kal_uint8 source )
{
sml_tmo_movial_sim_lock_context_struct * pObj = NULL;
if(NULL != pSMLTMMg[source].pObj)
{
kal_sys_trace("SML: object is exist!");
pSMLTMMg[source].pObj = NULL;
}
pObj = &(sml_tmo_movial_cntxt_obj[source]);
kal_mem_cpy(pObj,
pLidToObj,
sizeof(sml_tmo_movial_sim_lock_context_struct)
);
pSMLTMMg[source].pObj = pObj;
}
/*******************************************************************************
* FUNCTION
* sml_tmo_movial_take
* DESCRIPTION
* This method copys the contex of the SML object to the provided NVRAM LID.
* PARAMETERS
* OUT * pObjToLid
* RETURN
* void
* GLOBALS AFFECTED
* SMLTMMOBJ
*******************************************************************************/
void sml_tmo_movial_take( void *pObjToLid, kal_uint8 source )
{
sml_tmo_movial_sim_lock_context_struct * pObj = (sml_tmo_movial_sim_lock_context_struct *) pSMLTMMg[source].pObj;
if (NULL == pObjToLid || NULL == pObj)
{
return;
}
kal_mem_cpy(pObjToLid,
pObj,
sizeof(sml_tmo_movial_sim_lock_context_struct)
);
}
/*******************************************************************************
* FUNCTION
* sml_tmo_movial_destory
* DESCRIPTION
* This method free the SML object in memory if it is not used.
* PARAMETERS
* void
* RETURN
* void
* GLOBALS AFFECTED
* SMLTMMOBJ
*******************************************************************************/
void sml_tmo_movial_destory(kal_uint8 source)
{
pSMLTMMg[source].pObj = NULL;
}
/*******************************************************************************
* FUNCTION
* sml_tmo_movial_getItem
* DESCRIPTION
* This method returns the structure pointer and length of the structure
* of the desired SML object items.
* PARAMETERS
* IN cat
* IN item
* OUT *length
* RETURN
* void *
* GLOBALS AFFECTED
* SMLTMMOBJ
*******************************************************************************/
void *sml_tmo_movial_getItem( sml_tmo_movial_cat_enum category,
sml_ctx_enum item,
kal_uint16 *plength,
kal_uint8 source)
{
sml_tmo_movial_sim_lock_context_struct *pObj = (sml_tmo_movial_sim_lock_context_struct *) pSMLTMMg[source].pObj;
ASSERT(NULL != pObj);
switch(item)
{
case SML_TMO_MOVIAL_CAT_MAJOR_VERSION:
*plength = sizeof(kal_uint8);
return (kal_uint8 *) &(pObj->major_version);
case SML_TMO_MOVIAL_CAT_MINOR_VERSION:
*plength = sizeof(kal_uint8);
return (kal_uint8 *) &(pObj->minor_version);
case SML_TMO_MOVIAL_CAT_PROTECTION_ALGORITHM:
*plength = sizeof(kal_uint8);
return (kal_uint8 *) &(pObj->protection_algorithm);
case SML_TMO_MOVIAL_CAT_LOCK_OPERATION:
*plength = sizeof(kal_uint8);
return (kal_uint8 *) &(pObj->lock_operation);
case SML_TMO_MOVIAL_CAT_IMEI:
*plength = SML_TMO_MOVIAL_BLOB_IMEI_SIZE;
return (kal_uint8 *) &(pObj->imei[0]);
case SML_TMO_MOVIAL_CAT_TIME_STAMP:
*plength = SML_TMO_MOVIAL_BLOB_TIME_STAMP_SIZE;
return (kal_uint8 *) &(pObj->time_stamp[0]);
case SML_TMO_MOVIAL_CAT_START_TIME:
*plength = SML_TMO_MOVIAL_SIZE_OF_START_TIME;
return (kal_uint8 *) &(pObj->start_time[0]);
case SML_TMO_MOVIAL_CAT_UNLOCK_DURATION:
*plength = SML_TMO_MOVIAL_SIZE_OF_UNLOCK_DURATION;
return (kal_uint8 *) &(pObj->unlock_duration[0]);
case SML_TMO_MOVIAL_CAT_LENGTH:
*plength = SML_TMO_MOVIAL_BLOB_LENGTH_SIZE;
return (kal_uint16 *) &(pObj->length[0]);
case SML_TMO_MOVIAL_CAT_META:
*plength = sizeof(sml_tmo_movial_blob_meta_struct);
return (sml_tmo_movial_blob_meta_struct *) &(pObj->cat[category]);
case SML_TMO_MOVIAL_CAT_KEY:
*plength = sizeof(sml_tmo_movial_blob_key_struct);
return (sml_tmo_movial_blob_key_struct *) &(pObj->key[category]);
case SML_TMO_MOVIAL_CAT_SIGNATURE:
*plength = SML_TMO_MOVIAL_BLOB_SIZE_OF_SIGNATURE;
return (kal_uint8 *) &(pObj->signature[0]);
case SML_TMO_MOVIAL_CAT_UNLOCK_TIME_COUNTER:
*plength = SML_TMO_MOVIAL_SIZE_OF_UNLOCK_TIME;
return (kal_uint8 *) &(pObj->unlock_time[0]);
case SML_TMO_MOVIAL_CAT_CODE:
switch(category)
{
case SML_TMO_MOVIAL_CAT_N:
*plength = SML_TMO_MOVIAL_BLOB_CAT_N_SIZE;
return (kal_uint8 *) &(pObj->code_cat_n[0]);
break;
case SML_TMO_MOVIAL_CAT_NS:
*plength = SML_TMO_MOVIAL_BLOB_CAT_NS_SIZE;
return (kal_uint8 *) &(pObj->code_cat_ns[0]);
break;
case SML_TMO_MOVIAL_CAT_SP:
*plength = SML_TMO_MOVIAL_BLOB_CAT_SP_SIZE;
return (kal_uint8 *) &(pObj->code_cat_sp[0]);
break;
default:
/* do nothing */
break;
}
break;
default:
break;
}
return NULL;
}
void sml_tmo_movial_putItem( sml_tmo_movial_cat_enum category,
sml_ctx_enum item,
void *pItem,
kal_uint16 *plength,
kal_uint8 source)
{
sml_tmo_movial_sim_lock_context_struct *pObj = (sml_tmo_movial_sim_lock_context_struct *) pSMLTMMg[source].pObj;
ASSERT(NULL != pObj);
switch(item)
{
case SML_TMO_MOVIAL_CAT_UNLOCK_TIME_COUNTER:
kal_mem_cpy(&(pObj->unlock_time[0]),
pItem,
SML_TMO_MOVIAL_SIZE_OF_UNLOCK_TIME
);
break;
case SML_TMO_MOVIAL_CAT_LOCK_OPERATION:
kal_mem_cpy(&(pObj->lock_operation),
pItem,
*plength);
break;
default:
break;
}
}
kal_bool sml_tmo_movial_ValidateIMEI(kal_uint8 *imei, kal_bool is_bypass_default, kal_uint8 source)
{
kal_uint8 nvram_imei_bcd[8 + 1] = {0};
kal_uint8 nvram_imei_ascii[16 + 1] = {0};
kal_uint8 rec_id = 1 + l4c_gemini_get_actual_sim_id(source);
kal_bool result = KAL_FALSE;
#ifdef UNIT_TEST //Integrity check doesn't work on modis. Modify for UT.
kal_mem_cpy(&nvram_imei_bcd[0], &imei_bcd_ut[0], 9);
#else
if (nvram_get_imei_value(8, nvram_imei_bcd, rec_id) == KAL_TRUE)
#endif
{
if ((is_bypass_default == KAL_TRUE)
&& (KAL_TRUE == custom_check_is_default_imei(&nvram_imei_bcd[0])))
{
MD_TRC_INFO_SML_CUST_ALLOW_DEFAULT_IMEI();
result = KAL_TRUE;
}
else
{
// ch2-ch1, last digit is 0
nvram_imei_bcd[7] = nvram_imei_bcd[7] & 0x0f;
nvram_imei_bcd[8] = 0xff;
convert_to_digit((kal_uint8 *)nvram_imei_bcd, nvram_imei_ascii);
sml_mini_trace("UE IMEI", nvram_imei_ascii, SML_IMEI_PRINT_LEN);
sml_mini_trace("BLOB IMEI", &imei[0], SML_TMO_MOVIAL_BLOB_IMEI_SIZE);
if (kal_mem_cmp(&imei[0], nvram_imei_ascii, 15) == 0)
{
result = KAL_TRUE;
}
}
}
MD_TRC_INFO_SML_TMO_RSU_IMEI_CHECK_RESULT(result);
return result;
}
kal_bool sml_tmo_movial_ValidateTimeStamp(kal_uint8 *new_time_stamp, kal_uint8 source)
{
nvram_ef_sml_tmo_movial_sim_lock_obj_struct *p = &pSMLTMMg[source];
kal_uint16 length = 0;
kal_uint8 *blob_time_stamp;
kal_uint64 new_time = 0;
kal_uint64 blob_time = 0;
kal_uint8 i = 0;
blob_time_stamp = (kal_uint8 *)(*p->getItem)(SML_TMO_MOVIAL_CAT_NULL, SML_TMO_MOVIAL_CAT_TIME_STAMP, &length, source);
for (i = 0; i < SML_TMO_MOVIAL_BLOB_TIME_STAMP_SIZE-1; i++)
{
blob_time += blob_time_stamp[i];
blob_time = (blob_time << 8);
new_time += new_time_stamp[i];
new_time = (new_time << 8);
}
blob_time += blob_time_stamp[SML_TMO_MOVIAL_BLOB_TIME_STAMP_SIZE-1];
new_time += new_time_stamp[SML_TMO_MOVIAL_BLOB_TIME_STAMP_SIZE-1];
if (new_time > blob_time)
{
return KAL_TRUE;
}
return KAL_FALSE;
}
kal_bool sml_tmo_movial_ValidateConfigData(sml_tmo_movial_sim_lock_context_struct *pBlob)
{
kal_uint16 cat_idx, data_idx;
kal_uint16 length = 0;
kal_uint8 *data = NULL;
for (cat_idx = SML_TMO_MOVIAL_CAT_N ; cat_idx < SML_TMO_MOVIAL_CAT_SIZE ; cat_idx++)
{
switch (cat_idx)
{
case SML_TMO_MOVIAL_CAT_N:
length = pBlob->cat[cat_idx].num * SML_TMO_MOVIAL_BLOB_SIZE_OF_CAT_N;
data = pBlob->code_cat_n;
break;
case SML_TMO_MOVIAL_CAT_NS:
length = pBlob->cat[cat_idx].num * SML_TMO_MOVIAL_BLOB_SIZE_OF_CAT_NS;
data = pBlob->code_cat_ns;
break;
case SML_TMO_MOVIAL_CAT_SP:
length = pBlob->cat[cat_idx].num * SML_TMO_MOVIAL_BLOB_SIZE_OF_CAT_SP;
data = pBlob->code_cat_sp;
break;
default:
break;
}
for (data_idx = 0; data_idx < length; data_idx++)
{
if (!((data[data_idx] >= RMMI_CHAR_0) && (data[data_idx] <= RMMI_CHAR_9)) && (data[data_idx] != RMMI_CHAR_F))
{
return KAL_FALSE;
}
}
}
return KAL_TRUE;
}
/*******************************************************************************
* FUNCTION
* sml_tmo_movial_ConstructBlob
* DESCRIPTION
* This function construct full size Bolb (internal NV structure) from a variant length Blob received in response message
* PARAMETERS
* IN *pObj
* OUT pLen
* RETURN
* kal_uint8 * construct data
* GLOBALS AFFECTED
* SMLTMMOBJ
*******************************************************************************/
kal_uint8 *sml_tmo_movial_ConstructBlob(kal_uint8 *pObj, kal_uint16 slb_len, kal_uint8 *error_cause, kal_uint8 source)
{
kal_uint16 sizeM, sizeN, sizeP;
kal_uint16 length = 0;
kal_uint16 idx;
sml_tmo_movial_sim_lock_context_struct *pBlob;
kal_uint8 cat_idx = 0;
MD_TRC_FUNC_SML_TMO_MOVIAL_CONSTRUCTBLOB();
pBlob = (sml_tmo_movial_sim_lock_context_struct *)get_ctrl_buffer(SML_TMO_MOVIAL_MAX_BLOB_SIZE);
kal_mem_set(pBlob, 0, SML_TMO_MOVIAL_MAX_BLOB_SIZE);
/* major_version + minor_version + protection_algorithm + lock_operation */
pBlob->major_version = pObj[length++];
pBlob->minor_version = pObj[length++];
pBlob->protection_algorithm = pObj[length++];
pBlob->lock_operation = pObj[length++];
/* imei */
kal_mem_cpy(pBlob->imei, &(pObj[length]), SML_TMO_MOVIAL_BLOB_IMEI_SIZE);
length += SML_TMO_MOVIAL_BLOB_IMEI_SIZE;
/* time stamp */
kal_mem_cpy(pBlob->time_stamp, &(pObj[length]), SML_TMO_MOVIAL_BLOB_TIME_STAMP_SIZE);
length += SML_TMO_MOVIAL_BLOB_TIME_STAMP_SIZE;
/* Temporary unlock start timer */
kal_mem_cpy(pBlob->start_time, &(pObj[length]), SML_TMO_MOVIAL_SIZE_OF_START_TIME);
length += SML_TMO_MOVIAL_SIZE_OF_START_TIME;
/* Temporary unlock duration */
kal_mem_cpy(pBlob->unlock_duration, &(pObj[length]), SML_TMO_MOVIAL_SIZE_OF_UNLOCK_DURATION);
length += SML_TMO_MOVIAL_SIZE_OF_UNLOCK_DURATION;
/* length */
kal_mem_cpy(pBlob->length, &(pObj[length]), SML_TMO_MOVIAL_BLOB_LENGTH_SIZE);
length += SML_TMO_MOVIAL_BLOB_LENGTH_SIZE;
if (pBlob->protection_algorithm >= SML_TMO_MOVIAL_PROTECTION_SCHEME_SIZE)
{
*error_cause = SML_TMO_MOVIAL_SLB_ERR_GENERIC;
free_ctrl_buffer(pBlob);
return NULL;
}
if (sml_tmo_movial_ValidateIMEI(pBlob->imei, KAL_FALSE, source) == KAL_FALSE)
{
*error_cause = SML_TMO_MOVIAL_SLB_ERR_IMEI_MISMATCH;
free_ctrl_buffer(pBlob);
return NULL;
}
if (sml_tmo_movial_ValidateTimeStamp(pBlob->time_stamp, source) == KAL_FALSE)
{
*error_cause = SML_TMO_MOVIAL_SLB_ERR_GENERIC;
free_ctrl_buffer(pBlob);
return NULL;
}
idx = length;
for (cat_idx = SML_TMO_MOVIAL_CAT_N ; cat_idx < SML_TMO_MOVIAL_CAT_SIZE ; cat_idx++)
{
pBlob->cat[cat_idx].change_flag = pObj[idx++];
/* iteration_count, salt, hck */
kal_mem_cpy(pBlob->key[cat_idx].iteration_count, &(pObj[idx]), SML_TMO_MOVIAL_BLOB_ITERATION_COUNT_SIZE);
idx += SML_TMO_MOVIAL_BLOB_ITERATION_COUNT_SIZE;
kal_mem_cpy(pBlob->key[cat_idx].salt, &(pObj[idx]), SML_TMO_MOVIAL_BLOB_SALT_SIZE);
idx += SML_TMO_MOVIAL_BLOB_SALT_SIZE;
kal_mem_cpy(pBlob->key[cat_idx].hck, &(pObj[idx]), SML_TMO_MOVIAL_BLOB_HCK_SIZE);
idx += SML_TMO_MOVIAL_BLOB_HCK_SIZE;
/* check m,n,p */
if (pObj[idx] > 0)
{
switch (cat_idx)
{
case SML_TMO_MOVIAL_CAT_N:
sizeM = pObj[idx] * SML_TMO_MOVIAL_BLOB_SIZE_OF_CAT_N;
if (sizeM > SML_TMO_MOVIAL_BLOB_CAT_N_SIZE)
{
*error_cause = SML_TMO_MOVIAL_SLB_ERR_GENERIC;
free_ctrl_buffer(pBlob);
return NULL;
}
pBlob->cat[cat_idx].num = pObj[idx++];
kal_mem_cpy(pBlob->code_cat_n, &(pObj[idx]), sizeM);
idx += sizeM;
break;
case SML_TMO_MOVIAL_CAT_NS:
sizeN = pObj[idx] * SML_TMO_MOVIAL_BLOB_SIZE_OF_CAT_NS;
if (sizeN > SML_TMO_MOVIAL_BLOB_CAT_NS_SIZE)
{
*error_cause = SML_TMO_MOVIAL_SLB_ERR_GENERIC;
free_ctrl_buffer(pBlob);
return NULL;
}
pBlob->cat[cat_idx].num = pObj[idx++];
kal_mem_cpy(pBlob->code_cat_ns, &(pObj[idx]), sizeN);
idx += sizeN;
break;
case SML_TMO_MOVIAL_CAT_SP:
sizeP = pObj[idx] * SML_TMO_MOVIAL_BLOB_SIZE_OF_CAT_SP;
if (sizeP > SML_TMO_MOVIAL_BLOB_CAT_SP_SIZE)
{
*error_cause = SML_TMO_MOVIAL_SLB_ERR_GENERIC;
free_ctrl_buffer(pBlob);
return NULL;
}
pBlob->cat[cat_idx].num = pObj[idx++];
kal_mem_cpy(pBlob->code_cat_sp, &(pObj[idx]), sizeP);
idx += sizeP;
break;
default:
break;
}
}
else /* m/n/p = 0 */
{
/* memset ensures pBlob->cat[cat_idx].num set to 0 */
idx += 1;
}
}
if (sml_tmo_movial_ValidateConfigData(pBlob) == KAL_FALSE)
{
*error_cause = SML_TMO_MOVIAL_SLB_ERR_GENERIC;
free_ctrl_buffer(pBlob);
return NULL;
}
kal_mem_cpy(pBlob->signature, &(pObj[idx]), SML_TMO_MOVIAL_BLOB_SIZE_OF_SIGNATURE);
sml_Dump("constructed blob", (kal_uint8 *)pBlob, SML_TMO_MOVIAL_MAX_BLOB_SIZE);
return (kal_uint8 *)pBlob;
}
/*******************************************************************************
* FUNCTION
* sml_tmo_movial_ConstructSmlBlob
* DESCRIPTION
* This function constructs BLOB for NVRAM updating based on change_flag param
* change_flag == 0 => get cat / key / lock data from NVRAM
* change_flag == 1 => get cat / key / lock data from pObj
* PARAMETERS
* IN *pObj (constructed blob data)
* OUT pLen
* RETURN
* kal_uint8 * construct data
* GLOBALS AFFECTED
* SMLTMMOBJ
*******************************************************************************/
kal_uint8 *sml_tmo_movial_ConstructSmlBlob(sml_tmo_movial_sim_lock_context_struct *pObj, kal_uint8 source)
{
sml_tmo_movial_sim_lock_context_struct *psmlBlob;
kal_uint8 cat_idx = 0;
kal_uint16 obj_len = 0;
nvram_ef_sml_tmo_movial_sim_lock_obj_struct *p = &pSMLTMMg[source];
sml_tmo_movial_blob_meta_struct *cat = NULL;
sml_tmo_movial_blob_key_struct *key = NULL;
kal_uint8 *pdata = NULL;
psmlBlob = (sml_tmo_movial_sim_lock_context_struct *)get_ctrl_buffer(SML_TMO_MOVIAL_MAX_BLOB_SIZE);
kal_mem_set(psmlBlob, 0, SML_TMO_MOVIAL_MAX_BLOB_SIZE);
/* major_version + minor_version + protection_algorithm + lock_operation */
psmlBlob->major_version = pObj->major_version;
psmlBlob->minor_version= pObj->minor_version;
psmlBlob->protection_algorithm= pObj->protection_algorithm;
psmlBlob->lock_operation= pObj->lock_operation;
/* imei */
kal_mem_cpy(psmlBlob->imei, pObj->imei, SML_TMO_MOVIAL_BLOB_IMEI_SIZE);
/* time stamp */
kal_mem_cpy(psmlBlob->time_stamp, pObj->time_stamp, SML_TMO_MOVIAL_BLOB_TIME_STAMP_SIZE);
/* Temporary unlock start time */
kal_mem_cpy(psmlBlob->start_time, pObj->start_time, SML_TMO_MOVIAL_SIZE_OF_START_TIME);
/* Temporary unlock duration */
kal_mem_cpy(psmlBlob->unlock_duration, pObj->unlock_duration, SML_TMO_MOVIAL_SIZE_OF_UNLOCK_DURATION);
/* length */
kal_mem_cpy(psmlBlob->length, pObj->length, SML_TMO_MOVIAL_BLOB_LENGTH_SIZE);
for (cat_idx = SML_TMO_MOVIAL_CAT_N ; cat_idx < SML_TMO_MOVIAL_CAT_SIZE ; cat_idx++)
{
/* existing configuration should be used if change_flag=0 */
if (pObj->cat[cat_idx].change_flag == 0 || SML_TMO_MOVIAL_STATE_TEMPORARY_UNLOCK == psmlBlob->lock_operation)
{
cat = (sml_tmo_movial_blob_meta_struct *) (*p->getItem)(cat_idx, SML_TMO_MOVIAL_CAT_META, &obj_len, source);
key = (sml_tmo_movial_blob_key_struct *) (*p->getItem)(cat_idx, SML_TMO_MOVIAL_CAT_KEY, &obj_len, source);
pdata = (kal_uint8 *) (*p->getItem)(cat_idx, SML_TMO_MOVIAL_CAT_CODE, &obj_len, source);
}
else
{
cat = &(pObj->cat[cat_idx]);
key = &(pObj->key[cat_idx]);
switch (cat_idx)
{
case SML_TMO_MOVIAL_CAT_N:
pdata = pObj->code_cat_n;
break;
case SML_TMO_MOVIAL_CAT_NS:
pdata = pObj->code_cat_ns;
break;
case SML_TMO_MOVIAL_CAT_SP:
pdata = pObj->code_cat_sp;
break;
default:
break;
}
}
kal_mem_cpy(&(psmlBlob->cat[cat_idx]), cat, sizeof(sml_tmo_movial_blob_meta_struct));
kal_mem_cpy(&(psmlBlob->key[cat_idx]), key, sizeof(sml_tmo_movial_blob_key_struct));
switch (cat_idx)
{
case SML_TMO_MOVIAL_CAT_N:
kal_mem_cpy(psmlBlob->code_cat_n, pdata, SML_TMO_MOVIAL_BLOB_CAT_N_SIZE);
break;
case SML_TMO_MOVIAL_CAT_NS:
kal_mem_cpy(psmlBlob->code_cat_ns, pdata, SML_TMO_MOVIAL_BLOB_CAT_NS_SIZE);
break;
case SML_TMO_MOVIAL_CAT_SP:
kal_mem_cpy(psmlBlob->code_cat_sp, pdata, SML_TMO_MOVIAL_BLOB_CAT_SP_SIZE);
break;
default:
break;
}
}
kal_mem_cpy(psmlBlob->signature, pObj->signature, SML_TMO_MOVIAL_BLOB_SIZE_OF_SIGNATURE);
sml_Dump("constructed sml blob", (kal_uint8 *)psmlBlob, SML_TMO_MOVIAL_MAX_BLOB_SIZE);
return (kal_uint8 *)psmlBlob;
}
/*******************************************************************************
* FUNCTION
* sml_tmo_movial_ReconstructBlob
* DESCRIPTION
* This function restores the original message raw data from constructed internal blob structure
* (used for signature verification)
* PARAMETERS
* IN *pObj (constructed blob data)
* OUT pLen, length of returned raw data
* OUT error_cause
* RETURN
* kal_uint8 * raw data
* GLOBALS AFFECTED
* N/A
*******************************************************************************/
kal_uint8 *sml_tmo_movial_ReconstructBlob(sml_tmo_movial_sim_lock_context_struct *pObj, kal_uint32 *pLen, kal_uint8 *error_cause)
{
kal_uint8 *pData = NULL;
kal_uint32 blob_len, data_len;
kal_uint32 sizeM, sizeN, sizeP;
kal_uint32 len;
kal_uint8 cat_idx;
blob_len = sml_GetCount(&(pObj->length[0]));
sizeM = pObj->cat[SML_TMO_MOVIAL_CAT_N].num * SML_TMO_MOVIAL_BLOB_SIZE_OF_CAT_N;
sizeN = pObj->cat[SML_TMO_MOVIAL_CAT_NS].num * SML_TMO_MOVIAL_BLOB_SIZE_OF_CAT_NS;
sizeP = pObj->cat[SML_TMO_MOVIAL_CAT_SP].num * SML_TMO_MOVIAL_BLOB_SIZE_OF_CAT_SP;
/* RSA-PSS scheme */
if (pObj->protection_algorithm == 1)
{
data_len = blob_len - SML_TMO_MOVIAL_BLOB_SIZE_OF_SIGNATURE;
}
else
{
*error_cause = SML_TMO_MOVIAL_SLB_ERR_GENERIC;
return NULL;
}
pData = (kal_uint8 *)get_ctrl_buffer(data_len);
if (NULL == pData)
{
*error_cause = SML_TMO_MOVIAL_SLB_ERR_GENERIC;
return NULL;
}
/* major_version + minor_version + protection_algorithm + lock_operation */
len = 0;
pData[len++] = pObj->major_version;
pData[len++] = pObj->minor_version;
pData[len++] = pObj->protection_algorithm;
pData[len++] = pObj->lock_operation;
/* imei */
kal_mem_cpy((pData+len), pObj->imei, SML_TMO_MOVIAL_BLOB_IMEI_SIZE);
len += SML_TMO_MOVIAL_BLOB_IMEI_SIZE;
/* time stamp */
kal_mem_cpy((pData+len), pObj->time_stamp, SML_TMO_MOVIAL_BLOB_TIME_STAMP_SIZE);
len += SML_TMO_MOVIAL_BLOB_TIME_STAMP_SIZE;
/* temporary unlock start time */
kal_mem_cpy((pData+len), pObj->start_time, SML_TMO_MOVIAL_SIZE_OF_START_TIME);
len += SML_TMO_MOVIAL_SIZE_OF_START_TIME;
/* temporary unlock duration */
kal_mem_cpy((pData+len), pObj->unlock_duration, SML_TMO_MOVIAL_SIZE_OF_UNLOCK_DURATION);
len += SML_TMO_MOVIAL_SIZE_OF_UNLOCK_DURATION;
/* length */
kal_mem_cpy((pData+len), pObj->length, SML_TMO_MOVIAL_BLOB_LENGTH_SIZE);
len += SML_TMO_MOVIAL_BLOB_LENGTH_SIZE;
for (cat_idx = SML_TMO_MOVIAL_CAT_N ; cat_idx < SML_TMO_MOVIAL_CAT_SIZE; cat_idx++)
{
pData[len++] = pObj->cat[cat_idx].change_flag;
kal_mem_cpy((pData+len), (kal_uint8 *)&(pObj->key[cat_idx].iteration_count[0]), SML_TMO_MOVIAL_BLOB_ITERATION_COUNT_SIZE);
len += SML_TMO_MOVIAL_BLOB_ITERATION_COUNT_SIZE;
kal_mem_cpy((pData+len), (kal_uint8 *)&(pObj->key[cat_idx].salt[0]), SML_TMO_MOVIAL_BLOB_SALT_SIZE);
len += SML_TMO_MOVIAL_BLOB_SALT_SIZE;
kal_mem_cpy((pData+len), (kal_uint8 *)&(pObj->key[cat_idx].hck[0]), SML_TMO_MOVIAL_BLOB_HCK_SIZE);
len += SML_TMO_MOVIAL_BLOB_HCK_SIZE;
pData[len++] = pObj->cat[cat_idx].num;
switch (cat_idx)
{
case SML_TMO_MOVIAL_CAT_N:
kal_mem_cpy((pData+len), (kal_uint8 *)&(pObj->code_cat_n[0]), sizeM);
len += sizeM;
break;
case SML_TMO_MOVIAL_CAT_NS:
kal_mem_cpy((pData+len), (kal_uint8 *)&(pObj->code_cat_ns[0]), sizeN);
len += sizeN;
break;
case SML_TMO_MOVIAL_CAT_SP:
kal_mem_cpy((pData+len), (kal_uint8 *)&(pObj->code_cat_sp[0]), sizeP);
len += sizeP;
break;
default:
break;
}
}
*pLen = len;
sml_Dump("re-construct blob", pData, len);
return pData;
}
kal_bool sml_tmo_movial_checkValidity(void *pObj, kal_uint8 source, kal_uint8 *error_cause)
{
sml_tmo_movial_sim_lock_context_struct *pSmlObj = (sml_tmo_movial_sim_lock_context_struct *) pObj;
kal_uint8 *pData = NULL;
kal_bool result = KAL_FALSE;
kal_uint32 data_len;
if (sml_tmo_movial_ValidateIMEI(pSmlObj->imei, KAL_FALSE, source) == KAL_FALSE)
{
*error_cause = SML_TMO_MOVIAL_SLB_ERR_IMEI_MISMATCH;
return KAL_FALSE;
}
if (pSmlObj == NULL)
{
*error_cause = SML_TMO_MOVIAL_SLB_ERR_GENERIC;
return KAL_FALSE;
}
#ifdef UNIT_TEST
*error_cause = SML_TMO_MOVIAL_SLB_ERR_SUCCESS;
return KAL_TRUE;
#endif /* UNIT_TEST */
pData = sml_tmo_movial_ReconstructBlob(pSmlObj, &data_len, error_cause);
if (pData == NULL)
{
*error_cause = SML_TMO_MOVIAL_SLB_ERR_GENERIC;
return KAL_FALSE;
}
if (pSmlObj->protection_algorithm == SML_TMO_MOVIAL_PROTECTION_SCHEME_RSA2048)
{
TYPE_CUST_CHL_KEY key_handle = CUST_TM_PUB_KEY2;
t_cust_chl_asym_key key;
kal_uint32 ret;
kal_uint8 key_index = sbp_query_md_feature_data_by_ps(SBP_TMO_MOVIAL_SELECT_KEY_SET, source);
custom_tmo_movial_rsu_get_pub_key_handle(key_index, NULL, &key_handle);
ret = CustCHL_Get_Asym_Key(key_handle, &key);
if (ret == CUST_CHL_ERROR_NONE)
{
ret = CustCHL_Verify_PSS_Signature(CUST_CHL_ALG_RSA_PSS_SHA256, pData, data_len,
&pSmlObj->signature[0], &key);
MD_TRC_INFO_SMU_RSA_PSS_VERIFY_SIGNATURE_CUST(ret);
}
result = (ret == CUST_CHL_ERROR_NONE) ? KAL_TRUE : KAL_FALSE;
}
else
{
result = KAL_FALSE;
}
if (KAL_TRUE == result)
{
*error_cause = SML_TMO_MOVIAL_SLB_ERR_SUCCESS;
}
else
{
*error_cause = SML_TMO_MOVIAL_SLB_ERR_VERIFY_FAIL;
}
free_ctrl_buffer(pData);
return result;
}
void sml_tmo_movial_Load(void *pLid, kal_uint8 source)
{
nvram_ef_sml_tmo_movial_sim_lock_obj_struct *p = &pSMLTMMg[source];
/* Clean the old ones */
(*p->destory)(source);
/* Load the new one */
(*p->give)(pLid, source);
}
void sml_tmo_movial_FirstLoad(void *pLid, kal_uint8 source)
{
nvram_ef_sml_tmo_movial_sim_lock_obj_struct *p = &pSMLTMMg[source];
nvram_sml_tmo_movial_sim_lock_context_struct *pSmlObj = NULL;
#ifdef __TMO_RSU_OTP__
kal_bool is_default_blob = KAL_FALSE;
#endif /* __TMO_RSU_OTP__ */
pSmlObj = (nvram_sml_tmo_movial_sim_lock_context_struct *) pLid;
// Allow UE default IMEI (e.g. under factory procedure) in validate check
if (KAL_FALSE == sml_tmo_movial_ValidateIMEI(pSmlObj->imei, KAL_TRUE, source))
{
#ifdef __TMO_RSU_OTP__
is_default_blob = custom_check_is_default_tmo_blob(&(pSmlObj->imei[0]));
if (KAL_TRUE == is_default_blob)
{
kal_uint8 imei_bcd[8+1] = {0};
kal_uint8 rec_id = 1 + l4c_gemini_get_actual_sim_id(source);
if (nvram_get_imei_value(8, imei_bcd, rec_id) == KAL_TRUE)
{
kal_uint8 imei_ascii[16 + 1] = {0};
imei_bcd[7] = imei_bcd[7] & 0x0f;
imei_bcd[8] = 0xff;
convert_to_digit((kal_uint8 *)imei_bcd, imei_ascii);
MD_TRC_INFO_SML_TMO_RSU_COPY_IMEI();
kal_mem_cpy(&(pSmlObj->imei[0]), imei_ascii, SML_TMO_MOVIAL_BLOB_IMEI_SIZE);
}
}
else
#endif /* __TMO_RSU_OTP__ */
{
/* This can hit when BLOB/device IMEI is corrupted or hacked,
* hence ASSERT
*/
MD_TRC_WARNING_SML_CHECK_IMEI_FAILED();
// ASSERT(0);
}
}
/* Clean the old ones */
(*p->destory)(source);
/* Load the new one */
(*p->give)((void *)pSmlObj, source);
#ifdef __TMO_RSU_OTP__
if (KAL_TRUE == is_default_blob)
{
smu_nvram_write(NVRAM_EF_L4_SML_TMO_MOVIAL_SIM_LOCK_LID,
SML_TMO_MOVIAL_NVRAM_ACCESS_ID_UPDATE_SLB, KAL_FALSE);
}
#endif /* __TMO_RSU_OTP__ */
return;
}
/*******************************************************************************
* FUNCTION
* sml_tmo_movial_Save
* DESCRIPTION
* This function saves the SML obj to NVRAM LID
* PARAMETERS
* OUT pLid
* RETURN
* kal_uint16 Obj size
* GLOBALS AFFECTED
* SMLTMMOBJ
*******************************************************************************/
kal_uint16 sml_tmo_movial_Save(void *pLid, kal_uint8 source)
{
nvram_ef_sml_tmo_movial_sim_lock_obj_struct *p = &pSMLTMMg[source];
kal_uint16 length = sizeof(sml_tmo_movial_sim_lock_context_struct);
(*p->take)(pLid, source);
return length;
}
/*******************************************************************************
* FUNCTION
* sml_tmo_movial_CheckTempUnlock
* DESCRIPTION
* This method is to check if temporary unlock expires
* PARAMETERS
* IN source
* RETURN
* TRUE Temporary unlock expires
* FALSE Temporary unlock does not expire
* GLOBALS AFFECTED
* SMLTMMOBJ
*******************************************************************************/
kal_bool sml_tmo_movial_CheckTempUnlock(kal_uint8 source)
{
nvram_ef_sml_tmo_movial_sim_lock_obj_struct *p = &pSMLTMMg[source];
kal_uint8 *lock_operation, *unlock_duration;
kal_uint16 length;
kal_uint32 duration_seconds = 0;
kal_uint8 i;
lock_operation = (kal_uint8 *)(*p->getItem)(SML_TMO_MOVIAL_CAT_NULL, SML_TMO_MOVIAL_CAT_LOCK_OPERATION, &length, source);
unlock_duration = (kal_uint8 *)(*p->getItem)(SML_TMO_MOVIAL_CAT_NULL, SML_TMO_MOVIAL_CAT_UNLOCK_DURATION, &length, source);
for (i = 0; i < SML_TMO_MOVIAL_SIZE_OF_UNLOCK_DURATION-1; i++)
{
duration_seconds += unlock_duration[i];
duration_seconds = (duration_seconds << 8);
}
duration_seconds += unlock_duration[SML_TMO_MOVIAL_SIZE_OF_UNLOCK_DURATION-1];
MD_TRC_INFO_SML_CHECK_TEMP_UNLOCK(sml_tmo_movial_seconds_to_expire, duration_seconds);
if ((sml_tmo_movial_seconds_to_expire + (SML_TMO_MOVIAL_TIMEOUT_PERIODIC_CHECK/KAL_TICKS_1_SEC)) >= duration_seconds)
{
*lock_operation = SML_TMO_MOVIAL_STATE_PERMANENT_LOCK;
// Should reset SLB/NVRAM in following action
return KAL_TRUE;
}
else
{
sml_tmo_movial_seconds_to_expire += (SML_TMO_MOVIAL_TIMEOUT_PERIODIC_CHECK/KAL_TICKS_1_SEC);
(*p->putItem)(SML_TMO_MOVIAL_CAT_NULL, SML_TMO_MOVIAL_CAT_UNLOCK_TIME_COUNTER, &sml_tmo_movial_seconds_to_expire, &length, source);
// Should write back to NVRAM in following action
return KAL_FALSE;
}
}
/*******************************************************************************
* FUNCTION
* sml_tmo_movial_Catcode
* DESCRIPTION
* This function is used to compose the code of each category
* PARAMETERS
* IN cat
* IN *imsi
* IN *gid1
* IN mnc_len
* OUT *code
* RETURN
* kal_uint8 code length
* GLOBALS AFFECTED
* NONE
*******************************************************************************/
kal_uint8 sml_tmo_movial_Catcode( sml_tmo_movial_cat_enum cat,
kal_uint8 *imsi,
kal_uint8 *gid1,
kal_uint8 mnc_len,
kal_uint8 *code)
{
if(mnc_len == 3)
{
code[0] = ((imsi[1] & 0xF0) >> 4) + RMMI_CHAR_0;
code[1] = (imsi[2] & 0x0F) + RMMI_CHAR_0;
code[2] = ((imsi[2] & 0xF0) >> 4) + RMMI_CHAR_0;
code[3] = (imsi[3] & 0x0F) + RMMI_CHAR_0;
code[4] = ((imsi[3] & 0xF0) >> 4) + RMMI_CHAR_0;
code[5] = (imsi[4] & 0x0F) + RMMI_CHAR_0;
code[6] = ((imsi[4] & 0xF0) >> 4) + RMMI_CHAR_0;
code[7] = (imsi[5] & 0x0F) + RMMI_CHAR_0;
}
else
{
code[0] = ((imsi[1] & 0xF0) >> 4) + RMMI_CHAR_0;
code[1] = (imsi[2] & 0x0F) + RMMI_CHAR_0;
code[2] = ((imsi[2] & 0xF0) >> 4) + RMMI_CHAR_0;
code[3] = (imsi[3] & 0x0F) + RMMI_CHAR_0;
code[4] = ((imsi[3] & 0xF0) >> 4) + RMMI_CHAR_0;
code[5] = RMMI_CHAR_F; // MNC length is 2, so the 3rd digit will be 'F'
code[6] = (imsi[4] & 0x0F) + RMMI_CHAR_0;
code[7] = ((imsi[4] & 0xF0) >> 4) + RMMI_CHAR_0;
}
switch(cat)
{
case SML_TMO_MOVIAL_CAT_N:
return SML_TMO_MOVIAL_BLOB_SIZE_OF_CAT_N;
break;
case SML_TMO_MOVIAL_CAT_NS:
return SML_TMO_MOVIAL_BLOB_SIZE_OF_CAT_NS;
break;
case SML_TMO_MOVIAL_CAT_SP:
if(gid1 != NULL)
{
code[6] = gid1[0]; // + RMMI_CHAR_0
return SML_TMO_MOVIAL_BLOB_SIZE_OF_CAT_SP;
}
break;
default:
break;
}
return 0;
}
/*******************************************************************************
* FUNCTION
* sml_tmo_movial_GetCode
* DESCRIPTION
* This function is used to compose the code of each category whether
* mnc length is 2 or 3
* PARAMETERS
* cat [IN] category of the SIM-ME-Lock
* imsi [IN] imsi of the code source
* gid1 [IN] gid1 of the code source
* sim_mnc_len [IN] the mnc length decided by SIM
* pdata [IN] the saved code for comparing
* code [OUT] the composed code according to all input parameters
*
* RETURN
* kal_uint8
* GLOBALS AFFECTED
* SMLTMMOBJ
*******************************************************************************/
kal_uint8 sml_tmo_movial_GetCode( sml_tmo_movial_cat_enum cat,
kal_uint8 * imsi,
kal_uint8 * gid1,
kal_uint8 sim_mnc_len,
kal_uint8 * pdata,
kal_uint8 * code)
{
kal_uint8 mnc_len=0;
if (SML_MNC_LENGTH_NEST == 1)
{
mnc_len = sim_mnc_len;
}
else
{
if((*(pdata+5)) == 0x46 /* 'F' */)
{
mnc_len = 2;
}
else
{
mnc_len = 3;
}
}
return sml_tmo_movial_Catcode(cat, imsi, gid1, mnc_len, code);
}
/*******************************************************************************
* FUNCTION
* sml_tmo_movial_Check
* DESCRIPTION
* This function is used to check if the code is in the Pass list
* PARAMETERS
* IN cat
* IN *imsi
* IN *gid1
* IN sim_mnc_len
* IN source
* RETURN
* kal_bool
* GLOBALS AFFECTED
* SMLTMMOBJ
*******************************************************************************/
kal_bool sml_tmo_movial_Check( sml_tmo_movial_cat_enum cat, // category
kal_uint8 *imsi, // 9 bytes array, read from SIM, mandatory file
kal_uint8 *gid1, // 20 bytes array, read from SIM, NULL means gid1 invalid(file not exist)
kal_uint8 sim_mnc_len, // MNC length, read from SIM
kal_uint8 source) // 0:SIM1, 1:SIM2
{
nvram_ef_sml_tmo_movial_sim_lock_obj_struct *p = &pSMLTMMg[source];
sml_tmo_movial_blob_meta_struct *meta = NULL;
kal_uint8 *pdata = NULL;
kal_uint8 idx = 0;
kal_uint16 length = 0, offset = 0;
kal_bool result = KAL_FALSE;
kal_uint8 code_len = 0;
kal_uint8 code[10] = {0x00};
kal_uint8 size_of_cat = 0;
meta = (sml_tmo_movial_blob_meta_struct *) (*p->getItem)(cat, SML_TMO_MOVIAL_CAT_META, &length, source);
pdata = (kal_uint8 *) (*p->getItem)(cat, SML_TMO_MOVIAL_CAT_CODE, &length, source);
if ((meta->cat_lock == SML_TMO_MOVIAL_CAT_UNLOCKED) || (meta->num == 0))
{
return KAL_TRUE;
}
switch(cat)
{
case SML_TMO_MOVIAL_CAT_N:
{
size_of_cat = SML_TMO_MOVIAL_BLOB_SIZE_OF_CAT_N;
break;
}
case SML_TMO_MOVIAL_CAT_NS:
{
size_of_cat = SML_TMO_MOVIAL_BLOB_SIZE_OF_CAT_NS;
break;
}
case SML_TMO_MOVIAL_CAT_SP:
{
size_of_cat = SML_TMO_MOVIAL_BLOB_SIZE_OF_CAT_SP;
break;
}
default:
break;
}
for (idx = 0; idx < meta->num; idx++)
{
offset = idx * size_of_cat;
code_len = sml_tmo_movial_GetCode(cat,
imsi,
gid1,
sim_mnc_len,
(pdata+offset),
code);
if (size_of_cat == code_len)
{
if (kal_mem_cmp(code, (pdata+offset), code_len) == 0)
{
result = KAL_TRUE;
break;
}
}
}
return result;
}
/*******************************************************************************
* FUNCTION
* sml_tmo_movial_UpdateNwTimeAndCheckTempLock
* DESCRIPTION
* This method is to update newtork time and check if temporary lock expires
* PARAMETERS
* IN source
* IN nw_time_zone
* IN nw_time
* RETURN
* TRUE Temporary unlock expires
* FALSE Temporary unlock does not expire
* GLOBALS AFFECTED
* SMLOBJ
*******************************************************************************/
kal_bool sml_tmo_movial_UpdateNwTimeAndCheckTempLock(kal_uint8 source, kal_uint8 nw_time_zone, nw_time_zone_time_struct *nw_time)
{
nvram_ef_sml_tmo_movial_sim_lock_obj_struct *p = &pSMLTMMg[source];
kal_uint8 *start_time, *unlock_duration;
kal_uint8 *lock_operation = NULL;
kal_uint16 length;
kal_uint32 current_seconds = 0;
kal_uint64 start_seconds = 0;
kal_uint32 start_seconds_u32 = 0;
kal_uint32 duration_seconds = 0;
kal_uint8 i;
lock_operation = (kal_uint8 *)(*p->getItem)(SML_TMO_MOVIAL_CAT_NULL, SML_TMO_MOVIAL_CAT_LOCK_OPERATION, &length, source);
start_time = (kal_uint8 *)(*p->getItem)(SML_TMO_MOVIAL_CAT_NULL, SML_TMO_MOVIAL_CAT_START_TIME, &length, source);
unlock_duration = (kal_uint8 *)(*p->getItem)(SML_TMO_MOVIAL_CAT_NULL, SML_TMO_MOVIAL_CAT_UNLOCK_DURATION, &length, source);
if (*lock_operation != SML_TMO_MOVIAL_STATE_TEMPORARY_UNLOCK)
{
return KAL_FALSE;
}
/* calculate start time and duration in seconds */
start_seconds = 0;
for (i = 0; i < SML_TMO_MOVIAL_SIZE_OF_START_TIME-1; i++)
{
start_seconds += start_time[i];
start_seconds = (start_seconds << 8);
}
start_seconds += start_time[SML_TMO_MOVIAL_SIZE_OF_START_TIME-1];
start_seconds /= 1000; /* from milliseconds to seconds */
start_seconds_u32 = (kal_uint32)start_seconds;
duration_seconds = 0;
for (i = 0; i < SML_TMO_MOVIAL_SIZE_OF_UNLOCK_DURATION-1; i++)
{
duration_seconds += unlock_duration[i];
duration_seconds = (duration_seconds << 8);
}
duration_seconds += unlock_duration[SML_TMO_MOVIAL_SIZE_OF_UNLOCK_DURATION-1];
/* calculate current time in seconds */
current_seconds = sml_rsu_nwTimeToSeconds(nw_time_zone, nw_time);
MD_TRC_INFO_SML_TEMP_UNLOCK_TIME(start_seconds_u32, duration_seconds, current_seconds);
if (current_seconds >= (start_seconds_u32 + duration_seconds))
{
MD_TRC_INFO_SML_NW_TIME_EXPIRED();
return KAL_TRUE;
}
else
{
/* update unlock time for power off accuracy: start ---> unlock time ---> NITZ ---> power off/on ---> end */
sml_tmo_movial_seconds_to_expire = current_seconds - start_seconds_u32;
(*p->putItem)(SML_TMO_MOVIAL_CAT_NULL, SML_TMO_MOVIAL_CAT_UNLOCK_TIME_COUNTER, &sml_tmo_movial_seconds_to_expire, &length, source);
smu_nvram_write(NVRAM_EF_L4_SML_TMO_MOVIAL_SIM_LOCK_LID, SML_TMO_MOVIAL_NVRAM_ACCESS_ID_UNLOCK_EXPIRE, KAL_FALSE);
return KAL_FALSE;
}
}
/*******************************************************************************
* FUNCTION
* sml_tmo_movial_Verify
* DESCRIPTION
* This function is used to verify the SML lock keys
* PARAMETERS
* void
* RETURN
* kal_bool result
* GLOBALS AFFECTED
* SMLTMMOBJ
*******************************************************************************/
kal_bool sml_tmo_movial_Verify(sml_tmo_movial_cat_enum cat,
kal_uint8 * key,
kal_uint8 len,
kal_uint8 source)
{
nvram_ef_sml_tmo_movial_sim_lock_obj_struct *p = &pSMLTMMg[source];
sml_tmo_movial_blob_key_struct *catkey = NULL;
sml_tmo_movial_blob_meta_struct *meta = NULL;
kal_bool result = KAL_FALSE;
kal_uint16 length = 0;
kal_uint16 plength = 0;
kal_uint8 i = 0;
kal_uint32 blob_iter_count = 0;
catkey = (sml_tmo_movial_blob_key_struct *) (*p->getItem)(cat, SML_TMO_MOVIAL_CAT_KEY, &length, source);
meta = (sml_tmo_movial_blob_meta_struct *) (*p->getItem)(cat, SML_TMO_MOVIAL_CAT_META, &plength, source);
for (i = 0; i < SML_TMO_MOVIAL_BLOB_ITERATION_COUNT_SIZE-1; i++)
{
blob_iter_count += catkey->iteration_count[i];
blob_iter_count = (blob_iter_count << 8);
}
blob_iter_count += catkey->iteration_count[SML_TMO_MOVIAL_BLOB_ITERATION_COUNT_SIZE-1];
if (blob_iter_count != 0) /* blob has valid key data */
{
kal_uint32 verify_result = 0;
verify_result = cust_sec_hck_verify(TYPE_HCK_PBKDF2_HMAC_SHA256_SALT128,
(kal_char *)key, (kal_uint32)len,
catkey->salt,
blob_iter_count,
catkey->hck);
if (verify_result == ERR_SEC_CHECK_HCK_SUCCESS)
{
result = KAL_TRUE;
}
}
if (result == KAL_TRUE)
{
MD_TRC_INFO_SML_KEY_VERIFY_PASS_INFO_CUST();
/* Local unlock success; Unlock device permanently */
meta->cat_lock = SML_TMO_MOVIAL_CAT_UNLOCKED;
smu_nvram_write(NVRAM_EF_L4_SML_TMO_MOVIAL_SIM_LOCK_LID, SML_TMO_MOVIAL_NVRAM_ACCESS_ID_UPDATE_CAT_LOCK, KAL_FALSE);
}
else
{
MD_TRC_INFO_SML_KEY_VERIFY_FAIL_INFO_CUST();
}
return result;
}
kal_uint8 sml_tmo_movial_update_slb(void *blob, kal_uint8 source)
{
kal_uint8 *psmlBlob = NULL;
kal_uint8 error_cause = SML_TMO_MOVIAL_SLB_ERR_GENERIC;
sml_tmo_movial_sim_lock_context_struct *pBlob = (sml_tmo_movial_sim_lock_context_struct *)blob;
if (NULL == pBlob)
{
MD_TRC_INFO_SML_TMO_RSU_EMPTY_BLOB();
return SML_TMO_MOVIAL_SLB_ERR_BLOB_TOO_SHORT;
}
if (KAL_FALSE == sml_tmo_movial_checkValidity(pBlob, source, &error_cause))
{
MD_TRC_INFO_SML_TMO_RSU_BLOB_VALIDITY_FAIL();
return error_cause;
}
psmlBlob = sml_tmo_movial_ConstructSmlBlob((sml_tmo_movial_sim_lock_context_struct *)pBlob, source);
if (NULL != psmlBlob)
{
sml_tmo_movial_Load(psmlBlob, source);
free_ctrl_buffer(psmlBlob);
error_cause = SML_TMO_MOVIAL_SLB_ERR_SUCCESS;
}
return error_cause;
}
/*******************************************************************************
* FUNCTION
* sml_tmm_GetLockState
* DESCRIPTION
* This method is used to get SLB lock state
* PARAMETERS
* OUT lock state
* IN source
* RETURN
* void
* GLOBALS AFFECTED
* none
*******************************************************************************/
void sml_tmm_GetLockState(kal_uint8 *lock_state, kal_uint8 source)
{
nvram_ef_sml_tmo_movial_sim_lock_obj_struct *p = &pSMLTMMg[source];
kal_uint16 length;
kal_uint8 *slb_state;
slb_state = (kal_uint8 *)(*p->getItem)(SML_TMO_MOVIAL_CAT_NULL, SML_TMO_MOVIAL_CAT_LOCK_OPERATION, &length, source);
kal_mem_cpy(lock_state, slb_state, 1);
}
/*******************************************************************************
* FUNCTION
* sml_tmm_GetUnlockTimeLeft
* DESCRIPTION
* This method is used to get SLB unlock time left in seconds
* PARAMETERS
* IN source
* RETURN
* unlock time left
* GLOBALS AFFECTED
* none
*******************************************************************************/
kal_uint32 sml_tmm_GetUnlockTimeLeft(kal_uint8 source)
{
nvram_ef_sml_tmo_movial_sim_lock_obj_struct *p = &pSMLTMMg[source];
kal_uint16 length;
kal_uint8 *slb_end_time;
kal_uint32 duration_seconds = 0;
kal_uint8 i;
slb_end_time = (kal_uint8 *)(*p->getItem)(SML_TMO_MOVIAL_CAT_NULL, SML_TMO_MOVIAL_CAT_UNLOCK_DURATION, &length, source);
for (i = 0; i < (SML_TMO_MOVIAL_SIZE_OF_UNLOCK_DURATION - 1); i++)
{
duration_seconds += slb_end_time[i];
duration_seconds = (duration_seconds << 8);
}
duration_seconds += slb_end_time[SML_TMO_MOVIAL_SIZE_OF_UNLOCK_DURATION - 1];
MD_TRC_INFO_SML_TMO_RSU_GET_UNLOCK_TIME_LEFT(duration_seconds, sml_tmo_movial_seconds_to_expire);
if (sml_tmo_movial_seconds_to_expire >= duration_seconds)
{
return 0;
}
else
{
return (duration_seconds - sml_tmo_movial_seconds_to_expire);
}
}
/*******************************************************************************
* FUNCTION
* sml_tmo_movial_ConstructFirstBlob
* DESCRIPTION
* This function construct full size Bolb (internal NV structure) from a variant length Blob received from AP
* PARAMETERS
* IN *pObj
* OUT pLen
* RETURN
* kal_uint8 * construct data
* GLOBALS AFFECTED
* SMLTMMOBJ
*******************************************************************************/
kal_uint8 *sml_tmo_movial_ConstructFirstBlob(kal_uint8 *pObj, kal_uint16 slb_len, kal_uint8 source)
{
kal_uint16 sizeM, sizeN, sizeP;
kal_uint16 length = 0;
kal_uint16 idx;
sml_tmo_movial_sim_lock_context_struct *pBlob;
kal_uint8 cat_idx = 0;
MD_TRC_FUNC_SML_TMO_MOVIAL_CONSTRUCTFIRSTBLOB();
pBlob = (sml_tmo_movial_sim_lock_context_struct *)get_ctrl_buffer(SML_TMO_MOVIAL_MAX_BLOB_SIZE);
kal_mem_set(pBlob, 0, SML_TMO_MOVIAL_MAX_BLOB_SIZE);
/* major_version + minor_version + protection_algorithm + lock_operation */
pBlob->major_version = pObj[length++];
pBlob->minor_version = pObj[length++];
pBlob->protection_algorithm = pObj[length++];
pBlob->lock_operation = pObj[length++];
/* imei */
kal_mem_cpy(pBlob->imei, &(pObj[length]), SML_TMO_MOVIAL_BLOB_IMEI_SIZE);
length += SML_TMO_MOVIAL_BLOB_IMEI_SIZE;
/* time stamp */
kal_mem_cpy(pBlob->time_stamp, &(pObj[length]), SML_TMO_MOVIAL_BLOB_TIME_STAMP_SIZE);
length += SML_TMO_MOVIAL_BLOB_TIME_STAMP_SIZE;
/* Temporary unlock start timer */
kal_mem_cpy(pBlob->start_time, &(pObj[length]), SML_TMO_MOVIAL_SIZE_OF_START_TIME);
length += SML_TMO_MOVIAL_SIZE_OF_START_TIME;
/* Temporary unlock duration */
kal_mem_cpy(pBlob->unlock_duration, &(pObj[length]), SML_TMO_MOVIAL_SIZE_OF_UNLOCK_DURATION);
length += SML_TMO_MOVIAL_SIZE_OF_UNLOCK_DURATION;
/* length */
kal_mem_cpy(pBlob->length, &(pObj[length]), SML_TMO_MOVIAL_BLOB_LENGTH_SIZE);
length += SML_TMO_MOVIAL_BLOB_LENGTH_SIZE;
if (pBlob->protection_algorithm >= SML_TMO_MOVIAL_PROTECTION_SCHEME_SIZE)
{
free_ctrl_buffer(pBlob);
return NULL;
}
if (sml_tmo_movial_ValidateIMEI(pBlob->imei, KAL_FALSE, source) == KAL_FALSE)
{
MD_TRC_WARNING_SML_CHECK_IMEI_FAILED();
}
idx = length;
for (cat_idx = SML_TMO_MOVIAL_CAT_N ; cat_idx < SML_TMO_MOVIAL_CAT_SIZE ; cat_idx++)
{
pBlob->cat[cat_idx].change_flag = pObj[idx++];
/* iteration_count, salt, hck */
kal_mem_cpy(pBlob->key[cat_idx].iteration_count, &(pObj[idx]), SML_TMO_MOVIAL_BLOB_ITERATION_COUNT_SIZE);
idx += SML_TMO_MOVIAL_BLOB_ITERATION_COUNT_SIZE;
kal_mem_cpy(pBlob->key[cat_idx].salt, &(pObj[idx]), SML_TMO_MOVIAL_BLOB_SALT_SIZE);
idx += SML_TMO_MOVIAL_BLOB_SALT_SIZE;
kal_mem_cpy(pBlob->key[cat_idx].hck, &(pObj[idx]), SML_TMO_MOVIAL_BLOB_HCK_SIZE);
idx += SML_TMO_MOVIAL_BLOB_HCK_SIZE;
/* check m,n,p */
if (pObj[idx] > 0)
{
switch (cat_idx)
{
case SML_TMO_MOVIAL_CAT_N:
sizeM = pObj[idx] * SML_TMO_MOVIAL_BLOB_SIZE_OF_CAT_N;
if (sizeM > SML_TMO_MOVIAL_BLOB_CAT_N_SIZE)
{
free_ctrl_buffer(pBlob);
return NULL;
}
pBlob->cat[cat_idx].num = pObj[idx++];
kal_mem_cpy(pBlob->code_cat_n, &(pObj[idx]), sizeM);
idx += sizeM;
break;
case SML_TMO_MOVIAL_CAT_NS:
sizeN = pObj[idx] * SML_TMO_MOVIAL_BLOB_SIZE_OF_CAT_NS;
if (sizeN > SML_TMO_MOVIAL_BLOB_CAT_NS_SIZE)
{
free_ctrl_buffer(pBlob);
return NULL;
}
pBlob->cat[cat_idx].num = pObj[idx++];
kal_mem_cpy(pBlob->code_cat_ns, &(pObj[idx]), sizeN);
idx += sizeN;
break;
case SML_TMO_MOVIAL_CAT_SP:
sizeP = pObj[idx] * SML_TMO_MOVIAL_BLOB_SIZE_OF_CAT_SP;
if (sizeP > SML_TMO_MOVIAL_BLOB_CAT_SP_SIZE)
{
free_ctrl_buffer(pBlob);
return NULL;
}
pBlob->cat[cat_idx].num = pObj[idx++];
kal_mem_cpy(pBlob->code_cat_sp, &(pObj[idx]), sizeP);
idx += sizeP;
break;
default:
break;
}
}
else /* m/n/p = 0 */
{
/* memset ensures pBlob->cat[cat_idx].num set to 0 */
idx += 1;
}
}
if (sml_tmo_movial_ValidateConfigData(pBlob) == KAL_FALSE)
{
free_ctrl_buffer(pBlob);
return NULL;
}
kal_mem_cpy(pBlob->signature, &(pObj[idx]), SML_TMO_MOVIAL_BLOB_SIZE_OF_SIGNATURE);
sml_Dump("constructed blob", (kal_uint8 *)pBlob, SML_TMO_MOVIAL_MAX_BLOB_SIZE);
return (kal_uint8 *)pBlob;
}
#ifdef __TMO_RSU_OTP__
static kal_bool custom_check_is_default_tmo_blob(kal_uint8 *imei)
{
kal_uint8 otp_default_imei[SML_TMO_MOVIAL_BLOB_IMEI_SIZE] = {0x00};
if (kal_mem_cmp(&imei[0], &otp_default_imei[0], SML_TMO_MOVIAL_BLOB_IMEI_SIZE) == 0)
{
return KAL_TRUE;
}
else
{
return KAL_FALSE;
}
}
#endif /* __TMO_RSU_OTP__ */
/*******************************************************************************
* FUNCTION
* custom_check_is_default_imei
* DESCRIPTION
* Check if the IMEI is default IMEI
* PARAMETERS
* imei [kal_uint8 *]
* RETURN
* kal_bool
*******************************************************************************/
kal_bool custom_check_is_default_imei(kal_uint8 *imei)
{
#if defined(__SECURITY_OTP__) && defined(__NVRAM_OTP__)
kal_uint8 default_imei_bcd[8] = {0x00};
#else
kal_uint8 default_imei_bcd[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
#endif
if (NULL == imei)
{
return KAL_FALSE;
}
if (kal_mem_cmp(&imei[0], &default_imei_bcd[0], 8) == 0)
{
return KAL_TRUE;
}
else
{
return KAL_FALSE;
}
}
void custom_tmo_movial_rsu_get_pub_key_handle(kal_uint8 index,
TYPE_CUST_CHL_KEY *key1, TYPE_CUST_CHL_KEY *key2)
{
TYPE_CUST_CHL_KEY pub_key_group[][2] = {
// Pub Key 1, Pub Key 2
{CUST_TM_PUB_KEY1, CUST_TM_PUB_KEY2}, // index == 0
// Add handles of new pub keys sets here
};
#define TMO_MOVIAL_KEY_SET_MAX_NUM (sizeof(pub_key_group)/sizeof(pub_key_group[0]))
index = index > (TMO_MOVIAL_KEY_SET_MAX_NUM - 1) ? 0 : index;
if (NULL != key1)
{
*key1 = pub_key_group[index][0];
MD_TRC_INFO_SML_RSU_PUB_KEY_HANDLE((*key1));
}
if (NULL != key2)
{
*key2 = pub_key_group[index][1];
MD_TRC_INFO_SML_RSU_PUB_KEY_HANDLE((*key2));
}
return;
}
#endif /* L4_NOT_PRESENT */
#endif /* !defined(__MAUI_BASIC__) */