FreeCalypso > hg > tcs211-c139
diff g23m/condat/ms/src/aci_ext/aci_ext_pers.c @ 0:509db1a7b7b8
initial import: leo2moko-r1
author | Space Falcon <falcon@ivan.Harhan.ORG> |
---|---|
date | Mon, 01 Jun 2015 03:24:05 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/g23m/condat/ms/src/aci_ext/aci_ext_pers.c Mon Jun 01 03:24:05 2015 +0000 @@ -0,0 +1,1211 @@ +/* ++----------------------------------------------------------------------------- +| Project : +| Modul : J:\g23m-aci\aci_ext\aci_ext_pers.c ++----------------------------------------------------------------------------- +| Copyright 2002 Texas Instruments Berlin, AG +| All rights reserved. +| +| This file is confidential and a trade secret of Texas +| Instruments Berlin, AG +| The receipt of or possession of this file does not convey +| any rights to reproduce or disclose its contents or to +| manufacture, use, or sell anything it may describe, in +| whole, or in part, without the specific written consent of +| Texas Instruments Berlin, AG. ++----------------------------------------------------------------------------- +| Purpose : ++----------------------------------------------------------------------------- +*/ +#include "aci_all.h" + +#include "aci_cmh.h" +#include "ati_cmd.h" +#include "aci_cmd.h" + +#ifdef FAX_AND_DATA +#include "aci_fd.h" +#endif /* of #ifdef FAX_AND_DATA */ + +#ifndef WIN32 +#define ACI_PERSONALISTION_USE_FFS +#endif + +#include "aci.h" +#include "psa.h" +#include "psa_sim.h" +#include "psa_sms.h" +#include "psa_mmi.h" +#include "cmh.h" +#include "phb.h" +#include "aoc.h" + +#include "psa_sim.h" /* simShrdPrm */ + +#include "aci_ext_pers.h" +#include "aci_slock.h" + +#ifdef SIM_PERS +#include "general.h" // inluded for UINT8 compilation error in sec_drv.h +#include "sec_drv.h" +#endif + +#include "pcm.h" /* EF_SIMLCKEXT */ + +#ifdef MMI_SIMLOCK_TEST + #define ACI_PERSONALISTION_USE_FFS +#endif + +#ifdef ACI_PERSONALISTION_USE_FFS +#include "ffs/ffs.h" +#include "ffs_coat.h" +#endif /* ACI_PERSONALISTION_USE_FFS */ + + + +#define SLOCK_PCM_NRM 1 /* SIM lock data is stored as SIMLOCK to the PCM */ +#define SLOCK_PCM_EXT 2 /* SIM lock data is stored as SIMLOCKEXT to the PCM */ + +#ifdef SIM_PERS +#define TRUNCATION_KEY_LEN 8 /* */ +#endif + +#ifdef _SIMULATION_ +EF_SIMLCKEXT simlock_pcm_memory; /* emulates the PCM memory in WIN32 environment. */ +#endif + +#include "aci_ext_pers_cus.h" /* the customer specific personalisation data. */ + + + +LOCAL void aci_ext_personalisation_MMI_save( void ); + +static BOOL in_firstsimpersonalisation = FALSE; /* this will be set when the phone is powered up after FIRST_SIMLOCK */ +static BOOL pre_firstsimpersonalisation = FALSE; /* this will be set when a FIRST_SIM_LOCK is applied. All further locks + will not be applied but only prepare the lock for the next power-cycle */ +LOCAL void decodeB2A (U8 *bcd, U8 bcd_len, U8 *ascii); /* decode a BCD to ASCII */ +LOCAL void encodeA2B (char *ascii, UBYTE *bcd, UBYTE bcd_len); /* encode ASCII to BCD, fill up with 0xf */ +#ifdef SIM_PERS +EXTERN T_SEC_DRV_CONFIGURATION *cfg_data ; +EXTERN T_ACI_SIM_CONFIG aci_slock_sim_config; /* SIM configuration, initialised by a T_SIM_MMI_INSERT_IND */ +#endif + + + + +/* ++------------------------------------------------------------------------------ +| Function : aci_ext_personalisation_init ++------------------------------------------------------------------------------ +| Description : Initialisation of this extension. Might be used to initialise variables, set temporary data to default values and so on. + This method will be called once before any other public method of this extension. +| +| Parameters : void +| +| Return : void +| ++------------------------------------------------------------------------------ +*/ + + +void aci_ext_personalisation_init( void ) +{ +#ifdef SIM_PERS + T_SIMLOCK_TYPE lock_type; + T_SEC_DRV_RETURN status ; +#endif + + TRACE_FUNCTION("aci_ext_personalisation_init()"); + +#ifndef MMI_SIMLOCK_TEST + +#ifdef SIM_PERS + + for (lock_type=SIMLOCK_NETWORK;lock_type<= SIMLOCK_FIRST_SIM ;lock_type++) //prateek: changed loop till simlock_first_sim + { + switch (lock_type) + { + case SIMLOCK_NETWORK: + status =sec_get_REC (lock_type, &personalisation_nw); + if (status NEQ SEC_DRV_RET_Ok) + personalisation_nw = NULL; + else + { + AciSLockShrd.status[lock_type]=(T_SIMLOCK_STATUS)personalisation_nw->Header.Status; + AciSLockShrd.dependency[lock_type]=personalisation_nw->Header.Dependency; + } + break; + + case SIMLOCK_NETWORK_SUBSET: + status =sec_get_REC (lock_type, &personalisation_ns); + if (status NEQ SEC_DRV_RET_Ok) + personalisation_ns= NULL; + else + { + AciSLockShrd.status[lock_type]=(T_SIMLOCK_STATUS)personalisation_ns->Header.Status; + AciSLockShrd.dependency[lock_type]=personalisation_ns->Header.Dependency; + } + break; + + case SIMLOCK_SERVICE_PROVIDER: + status =sec_get_REC (lock_type, &personalisation_sp); + if (status NEQ SEC_DRV_RET_Ok) + personalisation_sp= NULL; + else + { + AciSLockShrd.status[lock_type]=(T_SIMLOCK_STATUS)personalisation_sp->Header.Status; + AciSLockShrd.dependency[lock_type]=personalisation_sp->Header.Dependency; + } + break; + + case SIMLOCK_CORPORATE: + status =sec_get_REC (lock_type, &personalisation_cp); + if (status NEQ SEC_DRV_RET_Ok) + personalisation_cp = NULL; + else + { + AciSLockShrd.status[lock_type]=(T_SIMLOCK_STATUS)personalisation_cp->Header.Status; + AciSLockShrd.dependency[lock_type]=personalisation_cp->Header.Dependency; + } + break; + + case SIMLOCK_SIM: + status =sec_get_REC (lock_type, &personalisation_sim); + if (status NEQ SEC_DRV_RET_Ok) + personalisation_sim = NULL; + else + { + AciSLockShrd.status[lock_type]=(T_SIMLOCK_STATUS)personalisation_sim->Header.Status; + AciSLockShrd.dependency[lock_type]=personalisation_sim->Header.Dependency; + } + break; + + case SIMLOCK_FIRST_SIM: + status =sec_get_REC (lock_type, &personalisation_first_sim); + if (status NEQ SEC_DRV_RET_Ok) + { + TRACE_FUNCTION("personalisation_first_sim = NULL"); + personalisation_first_sim = NULL; + } + else + { + AciSLockShrd.status[lock_type]=(T_SIMLOCK_STATUS)personalisation_first_sim->Header.Status; + AciSLockShrd.dependency[lock_type]=personalisation_first_sim->Header.Dependency; + } + break; + } + } +#endif //SIM_PERS + +#else /*for mmi testing, just read FFS*/ //MMI_SIMLOCK_TEST + +#endif //MMI_SIMLOCK_TEST +} + +#ifdef SIM_PERS + +/* ++------------------------------------------------------------------------------ +| Function : aci_ext_personalisation_free ++------------------------------------------------------------------------------ +| Description : Free the MEPD structure Memory +| +| Parameters : void +| +| Return : void +| ++------------------------------------------------------------------------------ +*/ +void aci_ext_personalisation_free( void ) +{ + T_SIMLOCK_TYPE lock_type; + + for (lock_type=SIMLOCK_NETWORK;lock_type<=SIMLOCK_FIRST_SIM;lock_type++) + { + switch (lock_type) + { + case SIMLOCK_NETWORK: + if(personalisation_nw NEQ NULL) + { + if(personalisation_nw->pBody NEQ NULL) + { + MFREE(personalisation_nw->pBody); + } + MFREE(personalisation_nw); + } + break; + + case SIMLOCK_NETWORK_SUBSET: + if(personalisation_ns NEQ NULL) + { + if(personalisation_ns->pBody NEQ NULL) + { + MFREE(personalisation_ns->pBody); + } + MFREE(personalisation_ns); + } + break ; + + case SIMLOCK_SERVICE_PROVIDER: + if(personalisation_sp NEQ NULL) + { + if(personalisation_sp->pBody NEQ NULL) + { + MFREE(personalisation_sp->pBody); + } + MFREE(personalisation_sp); + } + break ; + + case SIMLOCK_CORPORATE: + if(personalisation_cp NEQ NULL) + { + if(personalisation_cp->pBody NEQ NULL) + { + MFREE(personalisation_cp->pBody); + } + MFREE(personalisation_cp); + } + break ; + + case SIMLOCK_SIM: + if(personalisation_sim NEQ NULL) + { + if(personalisation_sim->pBody NEQ NULL) + { + MFREE(personalisation_sim->pBody); + } + MFREE(personalisation_sim); + } + break ; + + case SIMLOCK_FIRST_SIM: + if(personalisation_first_sim NEQ NULL) + { + MFREE(personalisation_first_sim); + } + break; + } + } +} + + + +/* + ACI extension method for retrieving the status of a single personalisation type. + The personalisation status is stored in a separate customer managed memory area + and the customer has to implement this extension method to return the actual status + of the questioned personalisation type. + */ +T_SIMLOCK_STATUS aci_ext_personalisation_get_status( T_SIMLOCK_TYPE personalisation_type ) +{ + TRACE_FUNCTION("aci_ext_personalisation_get_status()"); + #ifdef SIM_PERS + switch (personalisation_type) + { + case SIMLOCK_FIRST_SIM: /* should not occour */ + case SIMLOCK_SIM: + if(personalisation_sim NEQ NULL) + return personalisation_sim->Header.Status; + else + return SIMLOCK_FAIL; + + case SIMLOCK_NETWORK: + if(personalisation_nw NEQ NULL) + return personalisation_nw->Header.Status; + else + return SIMLOCK_FAIL; + + case SIMLOCK_NETWORK_SUBSET: + if(personalisation_ns NEQ NULL) + return personalisation_ns->Header.Status; + else + return SIMLOCK_FAIL; + + case SIMLOCK_SERVICE_PROVIDER: + if(personalisation_sp NEQ NULL) + return personalisation_sp->Header.Status; + else + return SIMLOCK_FAIL; + + case SIMLOCK_CORPORATE: + if(personalisation_cp NEQ NULL) + return personalisation_cp->Header.Status; + else + return SIMLOCK_FAIL; + + default: return SIMLOCK_FAIL; /* should not occour */ + } +#endif +} + + +/* ++------------------------------------------------------------------------------ +| Function : aci_ext_personalisation_verify_password ++------------------------------------------------------------------------------ +| Description : ACI extension method for verifying the passowrd. +|f the password is false then the counter is increased. If maxcnt is reached then the key +|will been blocked. If the password is correct then the counter is set to 0 +| +| Parameters : personalisation_type - category type (Network,Network subset, Service Provider,Corporate,SIM actegory) +| : passwd - category password +| +| Return : T_SIMLOCK_STATUS - Return SIMLOCK_DISABLED if compare key pass. +| - Return SIMLOCK_FAIL if compare key fails. +| - Return SIMLOCK_BLOCKED if FC counter is greater than +| FC Max. ++------------------------------------------------------------------------------ +*/ + + +T_SIMLOCK_STATUS aci_ext_personalisation_verify_password( T_SIMLOCK_TYPE personalisation_type, char *passwd) +{ + + T_SEC_DRV_RETURN ret; + UINT8 key_len = 0; /* For truncation check -Samir */ + + + TRACE_FUNCTION("aci_ext_personalisation_verify_password()"); + + + aci_slock_set_CFG(); + if(cfg_data EQ NULL) + { + return SIMLOCK_FAIL; + } + + if(cfg_data->Flags & SEC_DRV_HDR_FLAG_Truncation) + { + key_len = TRUNCATION_KEY_LEN; + } + ret = sec_cmp_KEY(personalisation_type, passwd, key_len) ; + MFREE(cfg_data); + + switch (ret) + { + case SEC_DRV_RET_Ok : + return SIMLOCK_DISABLED; + break; + + case SEC_DRV_RET_KeyWrong : + case SEC_DRV_RET_KeyMismatch: + /*Increment failure counter since input password is wrong*/ + ret = sec_FC_Increment(); + aci_slock_set_CFG(); + if(cfg_data EQ NULL) + { + return SIMLOCK_FAIL; + } + if(cfg_data->FC_Current >= cfg_data->FC_Max) + { + MFREE(cfg_data); + return SIMLOCK_BLOCKED; + } + else + { + MFREE(cfg_data); + return SIMLOCK_FAIL; + } + break; + + default:/*ERROR!- invalid input to sec_cmp_key OR some error in sec_cmp_key*/ + return SIMLOCK_FAIL; + break; + } + } + + +/* ++------------------------------------------------------------------------------ +| Function : aci_ext_personalisation_change_password ++------------------------------------------------------------------------------ +| Description : ACI extension method for verifying the passowrd. +|f the password is false then the counter is increased. If maxcnt is reached then the key +|will been blocked. If the password is correct then the counter is set to 0 +| +| Parameters : personalisation_type - category type (Network,Network subset, Service Provider,Corporate,SIM actegory) +| : passwd - category password +| : new_passwd - New Password + +| Return : T_SIMLOCK_STATUS - Return OPER_SUCCESS if changes password is successfull. +| - Return OPER_FAIL if changes password is fail. +| ++------------------------------------------------------------------------------ +*/ + +T_SIMLOCK_STATUS aci_ext_personalisation_change_password( T_SIMLOCK_TYPE personalisation_type, char *passwd, char *new_passwd ) +{ + T_SEC_DRV_RETURN retstat; + + retstat = sec_set_KEY (personalisation_type, passwd, new_passwd, 0); + switch(retstat) + { + case SEC_DRV_RET_Ok : + return OPER_SUCCESS; + case SEC_DRV_RET_FCExeeded : + AciSLockShrd.blocked = TRUE; + return SIMLOCK_BLOCKED ; + default : + return OPER_FAIL; + } + +} + + +/* ++------------------------------------------------------------------------------ +| Function : aci_ext_personalisation_set_status ++------------------------------------------------------------------------------ +| Description : ACI extension method for lock/unlock the category record +| +| Parameters : personalisation_type - category type (Network,Network subset, Service Provider,Corporate,SIM actegory) +| : lock - SIMLOCK_ENABLED to lock the category +| - SIMLOCK_DISABLED to unlock the category +| : passwd - category lock/unlock password +| +| +| Return : T_SIMLOCK_STATUS - Return SIMLOCK_ENABLED if lock is successfull. +| - Return SIMLOCK_DISABLED if unlock is successfull. +| - Return SIMLOCK_FAIL if lock or unlock fails +| - Return SIMLOCK_BLOCKED if FC exeeded for wrong password +| - Return SIMLOCK_FAIL if lock/unlock fail ++------------------------------------------------------------------------------ +*/ + +T_SIMLOCK_STATUS aci_ext_personalisation_set_status( T_SIMLOCK_TYPE personalisation_type, + T_SIMLOCK_STATUS lock, char* passwd) +{ + +//#ifdef SIM_PERS + int rec_num = personalisation_type; + int key_len = 0; + T_SEC_DRV_RETURN ret; + + TRACE_FUNCTION("aci_ext_personalisation_set_status()"); + + if(lock EQ SIMLOCK_ENABLED) + { + ret=sec_rec_Lock(rec_num, passwd, key_len,0xffff/*depend mask*/);/*aci_ext_personalisation_verify_password(personalisation_type, passwd);*/ + if (ret EQ SEC_DRV_RET_Ok){ + return SIMLOCK_ENABLED; + } + else{ + return SIMLOCK_FAIL; + } + } + + if(lock EQ SIMLOCK_DISABLED) + { + if(cfg_data->Flags & SEC_DRV_HDR_FLAG_Truncation) + { + key_len = TRUNCATION_KEY_LEN; + } + ret = sec_rec_Unlock(rec_num,TEMPORARY_UNLOCK,passwd,key_len,0xffff/*depend mask*/); + if (ret EQ SEC_DRV_RET_Ok){ + return SIMLOCK_DISABLED; + } + else{ + if(ret EQ SEC_DRV_RET_FCExeeded) + { + return SIMLOCK_BLOCKED; + } + return SIMLOCK_FAIL; + } + } + return SIMLOCK_FAIL; + //#endif +} + + + + +//#ifdef SIM_PERS + +/* ++------------------------------------------------------------------------------ +| Function : aci_ext_slock_reset_fc ++------------------------------------------------------------------------------ +| Description : For Failure Counter reset. Uses Security Drv. method to reset FC +| +| Parameters : fckey - Password for resetting FC counter +| +| +| Return : T_OPER_RET_STATUS - Return OPER_SUCCESS if FC reset is successfull. +| - Return OPER_FAIL if FC reset is fail +| ++------------------------------------------------------------------------------ +*/ + + +T_OPER_RET_STATUS aci_ext_slock_reset_fc(char *fckey) +{ + T_SEC_DRV_RETURN retstat; + + TRACE_FUNCTION("aci_ext_slock_reset_fc ()"); + + if ((retstat= sec_FC_Reset(fckey,0)) NEQ SEC_DRV_RET_Ok) + { + return OPER_FAIL; + } + else{ + return OPER_SUCCESS; + } +} + + + +/* ++------------------------------------------------------------------------------ +| Function : aci_ext_slock_sup_info ++------------------------------------------------------------------------------ +| Description : For Supplementary Info( e.g. FC MAX, FC Current value). +| +| Parameters : sup_info -which has the element info type and Data value. +| +| +| Return : T_OPER_RET_STATUS - Return OPER_SUCCESS if successfully read the Info type data +| value from security driver. Info type data value is filled in this +| Function +| - Return OPER_FAIL if unable to read Info type data value from +| security driverl +| ++------------------------------------------------------------------------------ +*/ + + +T_OPER_RET_STATUS aci_ext_slock_sup_info (T_SUP_INFO *sup_info) +{ + T_SEC_DRV_RETURN retstat; + T_SEC_DRV_CONFIGURATION *cfg_data; + + TRACE_FUNCTION("aci_ext_slock_sup_info ()"); + + if ((retstat= sec_get_CFG(&cfg_data)) NEQ SEC_DRV_RET_Ok) + return OPER_FAIL; + else + { + switch(sup_info->infoType ) + { + case(FCMAX ): sup_info->datavalue = cfg_data->FC_Max; break; + case(FCATTEMPTSLEFT): sup_info->datavalue = ((cfg_data->FC_Max) - (cfg_data->FC_Current)); break; + case(FCRESETFAILMAX ): sup_info->datavalue = cfg_data->FC_Reset_Fail_Max ; break; + case(FCRESETFAILATTEMPTSLEFT): sup_info->datavalue = ((cfg_data->FC_Reset_Fail_Max) - (cfg_data->FC_Reset_Fail_Current)); break; + case(FCRESETSUCCESSMAX ): sup_info->datavalue = cfg_data->FC_Reset_Success_Max ; break; + case(FCRESETSUCCESSATTEMPTSLEFT): sup_info->datavalue = ((cfg_data->FC_Reset_Success_Max) - (cfg_data->FC_Reset_Success_Current)); break; + case (TIMERFLAG): sup_info->datavalue =(cfg_data->Flags & SEC_DRV_HDR_FLAG_Unlock_Timer)?(1):(0) ;break; + case (ETSIFLAG) : sup_info->datavalue =(cfg_data->Flags & SEC_DRV_HDR_FLAG_ETSI_Flag)?(1):(0) ; break; + case (AIRTELINDFLAG) : sup_info->datavalue =(cfg_data->Flags & SEC_DRV_HDR_FLAG_Airtel_Ind)?(1):(0) ; break; + } /*end of switch*/ + + MFREE(cfg_data);/* deallocate configuration data allocated from Security Driver; */ + return OPER_SUCCESS; + } +} + + +/* ++------------------------------------------------------------------------------ +| Function : aci_ext_auto_personalise ++------------------------------------------------------------------------------ +| Description : It Auto personalise the sim. If Add new IMSI flag set and If Code is not present +| then adds the code in the MEPD data and lock the category ( Network, Sub Network, +| sim ) +| Parameters : void +| +| +| Return : void +| ++------------------------------------------------------------------------------ +*/ + +T_AUTOLOCK_STATUS aci_ext_auto_personalise(T_SIMLOCK_TYPE current_lock) +{ + UBYTE imsi_sim[MAX_IMSI_LEN+1]; + T_SIMLOCK_TYPE type; + static UINT16 flag = 0xffff; + UINT16 dependMask = 0xffff; + + TRACE_FUNCTION("aci_ext_auto_personalise()"); + + psaSIM_decodeIMSI(simShrdPrm.imsi.field, simShrdPrm.imsi.c_field, (char *)imsi_sim); + + if((AciSLockShrd.dependency[SIMLOCK_FIRST_SIM] & NW_AUTO_LOCK)AND (flag & NW_AUTO_LOCK)) + { + type = SIMLOCK_NETWORK; + sim_code_present_in_me = FALSE; + aci_slock_check_NWlock(imsi_sim,1); + flag &= ~(NW_AUTO_LOCK); + + if(sim_code_present_in_me EQ FALSE) + { + aci_ext_add_code(type); + } + } + + if((AciSLockShrd.dependency[SIMLOCK_FIRST_SIM] & NS_AUTO_LOCK)AND (flag & NS_AUTO_LOCK)) + { + type = SIMLOCK_NETWORK_SUBSET; + flag &= ~(NS_AUTO_LOCK); + sim_code_present_in_me = FALSE; + aci_slock_check_NSlock(imsi_sim,1); + if(sim_code_present_in_me EQ FALSE) + { + aci_ext_add_code(type); + } + } + + if((AciSLockShrd.dependency[SIMLOCK_FIRST_SIM] & SIM_AUTO_LOCK ) AND (flag & SIM_AUTO_LOCK)) + { + flag &= ~(SIM_AUTO_LOCK); + type = SIMLOCK_SIM; + sim_code_present_in_me = FALSE; + aci_slock_check_SMlock(imsi_sim,1); + if(sim_code_present_in_me EQ FALSE) + { + aci_ext_add_code(type); + } + } + + if((AciSLockShrd.dependency[SIMLOCK_FIRST_SIM] & SP_AUTO_LOCK) AND (flag & SP_AUTO_LOCK)) + { + if (psaSIM_ChkSIMSrvSup(SRV_GrpLvl1)) + { + if(aci_slock_sim_config.sim_read_gid1 EQ FALSE) + { + aci_slock_sim_read_sim(SIM_GID1, NOT_PRESENT_8BIT, MAX_GID); + return AUTOLOCK_EXCT ; + } + else + { + type = SIMLOCK_SERVICE_PROVIDER; + sim_code_present_in_me = FALSE; + aci_slock_check_SPlock(imsi_sim,1); + TRACE_FUNCTION_P1("SP sim_code_present_in_me = %d", sim_code_present_in_me); + switch(sim_code_present_in_me) + { + case FALSE : + aci_ext_add_code(type); + break; + case CHECK_FAIL : + dependMask &= ~(SP_AUTO_LOCK) ; + break; + case TRUE : + break; + } + flag &= ~(SP_AUTO_LOCK); + + } + } + else + { + flag &= ~(SP_AUTO_LOCK); + dependMask &= ~(SP_AUTO_LOCK) ; + } + } + + +if((AciSLockShrd.dependency[SIMLOCK_FIRST_SIM] & CP_AUTO_LOCK)AND (flag & CP_AUTO_LOCK)) + { + + if (psaSIM_ChkSIMSrvSup(SRV_GrpLvl1)) + { + if(aci_slock_sim_config.sim_read_gid1 EQ FALSE) + { + aci_slock_sim_read_sim(SIM_GID1, NOT_PRESENT_8BIT, MAX_GID); + return AUTOLOCK_EXCT ; + } + } + + if (psaSIM_ChkSIMSrvSup(SRV_GrpLvl2)) + { + if(aci_slock_sim_config.sim_read_gid2 EQ FALSE) + { + aci_slock_sim_read_sim(SIM_GID2, NOT_PRESENT_8BIT, MAX_GID); + return AUTOLOCK_EXCT ; + } + } + + if(psaSIM_ChkSIMSrvSup(SRV_GrpLvl1) AND psaSIM_ChkSIMSrvSup(SRV_GrpLvl2)) + { + type = SIMLOCK_CORPORATE; + sim_code_present_in_me = FALSE; + aci_slock_check_CPlock(imsi_sim,1); + switch(sim_code_present_in_me) + { + case FALSE : + aci_ext_add_code(type); + break; + case CHECK_FAIL : + dependMask &= ~(CP_AUTO_LOCK) ; + break; + case TRUE : + break; + } + flag &= ~(CP_AUTO_LOCK); + } + else + { + flag &= ~(CP_AUTO_LOCK); + dependMask &= ~(CP_AUTO_LOCK) ; + } + +} + + + sec_rec_Lock(SIMLOCK_FIRST_SIM,NULL,0,dependMask); + return AUTOLOCK_CMPL ; + +} + + + + +/* ++------------------------------------------------------------------------------ +| Function : aci_ext_add_code ++------------------------------------------------------------------------------ +| Description : It append the category code in MEPD. It foolows FIFO procedure while adding the code +| Parameters : type -- category type (Network,Network subset, Service Provider,Corporate,SIM actegory) +| Return : void +| ++------------------------------------------------------------------------------ +*/ + + +void aci_ext_add_code(T_SIMLOCK_TYPE type) +{ + UINT16 index =0; + UBYTE max_num_user_codes; + UBYTE num_user_codes; + UBYTE curr_user_code_index; + UBYTE imsi_field[20]; + + TRACE_FUNCTION("aci_ext_add_code()"); + switch (type) + { + case SIMLOCK_NETWORK : + max_num_user_codes =((UBYTE *) personalisation_nw->pBody)[index]; + index += MAX_NUM_USERCODE_SIZE; + index += NUM_OPCODE_SIZE ; + index += OPCODE_LEN_SIZE + ((UBYTE *) personalisation_nw->pBody)[OPCODE_LEN_INDEX]; + + num_user_codes = ((UBYTE *)personalisation_nw->pBody)[index]; + index +=NUM_USER_CODE_SIZE; + curr_user_code_index = ((UBYTE *)personalisation_nw->pBody)[index]; + index += CURR_USER_CODE_INDEX_SIZE ; + + memcpy(imsi_field,simShrdPrm.imsi.field,simShrdPrm.imsi.c_field); + if(simShrdPrm.mnc_len EQ 3) + imsi_field[NW_CODE_LEN-1] |= 0xf0; + else + imsi_field[NW_CODE_LEN-1] |= 0xff; + + /* + * If no user code is present, curr_user_code_index will be ff. After that, curr_user_code_index starts from 0 + */ + if((curr_user_code_index EQ 0xff) || (curr_user_code_index EQ max_num_user_codes -1)) + curr_user_code_index = 0; + else + curr_user_code_index++; + + if(num_user_codes < max_num_user_codes) + num_user_codes++; + + memcpy(&((UBYTE *)personalisation_nw->pBody)[index + curr_user_code_index*NW_CODE_LEN/*multiplication added*/],imsi_field,NW_CODE_LEN); + ((UBYTE *)personalisation_nw->pBody)[index - CURR_USER_CODE_INDEX_SIZE] = curr_user_code_index; + ((UBYTE *)personalisation_nw->pBody)[index - CURR_USER_CODE_INDEX_SIZE - NUM_USER_CODE_SIZE] = num_user_codes; + sec_set_REC(type, personalisation_nw); + break; + + + case SIMLOCK_NETWORK_SUBSET : + max_num_user_codes = ((UBYTE *)personalisation_ns->pBody)[index]; + index += MAX_NUM_USERCODE_SIZE; + index += NUM_OPCODE_SIZE ; + index += OPCODE_LEN_SIZE + ((UBYTE *) personalisation_ns->pBody)[OPCODE_LEN_INDEX]; + + num_user_codes = ((UBYTE *) personalisation_ns->pBody)[index]; + index +=NUM_USER_CODE_SIZE; + curr_user_code_index = ((UBYTE *)personalisation_ns->pBody)[index]; + index += CURR_USER_CODE_INDEX_SIZE ; + + memcpy(imsi_field,simShrdPrm.imsi.field,simShrdPrm.imsi.c_field); + if(simShrdPrm.mnc_len EQ 3) + imsi_field[NW_NS_CODE_LEN-1] |= 0xf0; //prateek: unused nibbles to be '00' and not 'FF' to avoid problems during decodeIMSI + else + imsi_field[NW_NS_CODE_LEN-1] |= 0xff; + + /* + * If no user code is present, curr_user_code_index will be ff. After that, curr_user_code_index starts from 0 + */ + if((curr_user_code_index EQ 0xff) || (curr_user_code_index EQ max_num_user_codes -1)) + curr_user_code_index = 0; + else + curr_user_code_index++; + + if(num_user_codes < max_num_user_codes) + num_user_codes++; + + memcpy(&((UBYTE *)personalisation_ns->pBody)[index + curr_user_code_index*NW_NS_CODE_LEN/*multiplication added*/],imsi_field,NW_NS_CODE_LEN); + ((UBYTE *)personalisation_ns->pBody)[index - CURR_USER_CODE_INDEX_SIZE] = curr_user_code_index; + ((UBYTE *)personalisation_ns->pBody)[index - CURR_USER_CODE_INDEX_SIZE - NUM_USER_CODE_SIZE] = num_user_codes; + sec_set_REC(type, personalisation_ns); + break; + + case SIMLOCK_SERVICE_PROVIDER : + if(!psaSIM_ChkSIMSrvSup(SRV_GrpLvl1) OR (aci_slock_sim_config.sim_gidl1[0] EQ 0xff)) + { + TRACE_FUNCTION("not adding sp as no service or maybe gid1 is ff"); + break; + } + + max_num_user_codes =((UBYTE *) personalisation_sp->pBody)[index]; + index += MAX_NUM_USERCODE_SIZE; + index += NUM_OPCODE_SIZE ; + index += OPCODE_LEN_SIZE + ((UBYTE *)personalisation_sp->pBody)[OPCODE_LEN_INDEX]; + + num_user_codes = ((UBYTE *)personalisation_sp->pBody)[index]; + index +=NUM_USER_CODE_SIZE; + curr_user_code_index = ((UBYTE *)personalisation_sp->pBody)[index]; + index += CURR_USER_CODE_INDEX_SIZE ; + + memcpy(imsi_field,simShrdPrm.imsi.field,simShrdPrm.imsi.c_field); + if(simShrdPrm.mnc_len EQ 3) + imsi_field[NW_CODE_LEN-1] |= 0xf0; //prateek: unused nibbles to be '00' and not 'FF' to avoid problems during decodeIMSI + else + imsi_field[NW_CODE_LEN-1] |= 0xff; + + if (psaSIM_ChkSIMSrvSup(SRV_GrpLvl1)) + { + memcpy(imsi_field+NW_CODE_LEN,aci_slock_sim_config.sim_gidl1,GID1_LEN); + /* + * If no user code is present, curr_user_code_index will be ff. After that, curr_user_code_index starts from 0 + */ + if((curr_user_code_index EQ 0xff) || (curr_user_code_index EQ max_num_user_codes -1)) + curr_user_code_index = 0; + else + curr_user_code_index++; + + if(num_user_codes < max_num_user_codes) + num_user_codes++; + + memcpy(&((UBYTE *)personalisation_sp->pBody)[index + curr_user_code_index*(NW_CODE_LEN+GID1_LEN)],imsi_field,NW_CODE_LEN+GID1_LEN); + ((UBYTE *)personalisation_sp->pBody)[index - CURR_USER_CODE_INDEX_SIZE] = curr_user_code_index; + ((UBYTE *)personalisation_sp->pBody)[index - CURR_USER_CODE_INDEX_SIZE - NUM_USER_CODE_SIZE] = num_user_codes; + sec_set_REC(type, personalisation_sp); + } + break; + + case SIMLOCK_CORPORATE : + if( !psaSIM_ChkSIMSrvSup(SRV_GrpLvl1) OR !psaSIM_ChkSIMSrvSup(SRV_GrpLvl2) OR (aci_slock_sim_config.sim_gidl1[0] EQ 0xff) OR (aci_slock_sim_config.sim_gidl2[0] EQ 0xff)) + { + TRACE_FUNCTION("not adding cp as no service or maybe gid1/gid2 is ff"); + break; + } + + max_num_user_codes = ((UBYTE *)personalisation_cp->pBody)[index]; + index += MAX_NUM_USERCODE_SIZE; + index += NUM_OPCODE_SIZE ; + index += OPCODE_LEN_SIZE + ((UBYTE *)personalisation_cp->pBody)[OPCODE_LEN_INDEX]; + + num_user_codes = ((UBYTE *)personalisation_cp->pBody)[index]; + index +=NUM_USER_CODE_SIZE; + curr_user_code_index =((UBYTE *) personalisation_cp->pBody)[index]; + index += CURR_USER_CODE_INDEX_SIZE ; + + memcpy(imsi_field,simShrdPrm.imsi.field,simShrdPrm.imsi.c_field); + if(simShrdPrm.mnc_len EQ 3) + imsi_field[NW_CODE_LEN-1] |= 0xf0; //prateek: unused nibbles to be '00' and not 'FF' to avoid problems during decodeIMSI + else + /* if(curr_user_code_index NEQ 0) */ + imsi_field[NW_CODE_LEN-1] |= 0xff; + + if (psaSIM_ChkSIMSrvSup(SRV_GrpLvl1)) + { + memcpy(imsi_field+NW_CODE_LEN,aci_slock_sim_config.sim_gidl1,GID1_LEN); + if (psaSIM_ChkSIMSrvSup(SRV_GrpLvl2)) + { + memcpy(imsi_field+NW_CODE_LEN+GID1_LEN,aci_slock_sim_config.sim_gidl2,GID2_LEN); + /* + * If no user code is present, curr_user_code_index will be ff. After that, curr_user_code_index starts from 0 + */ + if((curr_user_code_index EQ 0xff) || (curr_user_code_index EQ max_num_user_codes -1)) + curr_user_code_index = 0; + else + curr_user_code_index++; + + if(num_user_codes < max_num_user_codes) + num_user_codes++; + + memcpy(&((UBYTE *)personalisation_cp->pBody)[index + (curr_user_code_index*(NW_CODE_LEN+GID1_LEN+GID2_LEN))],imsi_field,NW_CODE_LEN+GID1_LEN+GID2_LEN); + ((UBYTE *)personalisation_cp->pBody)[index - CURR_USER_CODE_INDEX_SIZE] = curr_user_code_index; + ((UBYTE *)personalisation_cp->pBody)[index - CURR_USER_CODE_INDEX_SIZE - NUM_USER_CODE_SIZE] = num_user_codes; + sec_set_REC(type, personalisation_cp); + } + } + break; + + case SIMLOCK_SIM : + max_num_user_codes = ((UBYTE *)personalisation_sim->pBody)[index]; + index += MAX_NUM_USERCODE_SIZE; + index += NUM_OPCODE_SIZE ; + index += OPCODE_LEN_SIZE + ((UBYTE *)personalisation_sim->pBody)[OPCODE_LEN_INDEX]; + + num_user_codes = ((UBYTE *)personalisation_sim->pBody)[index]; + index +=NUM_USER_CODE_SIZE; + curr_user_code_index =((UBYTE *) personalisation_sim->pBody)[index]; + index += CURR_USER_CODE_INDEX_SIZE ; + + memcpy(imsi_field,simShrdPrm.imsi.field,simShrdPrm.imsi.c_field); + + /* + * If no user code is present, curr_user_code_index will be ff. After that, curr_user_code_index starts from 0 + */ + if((curr_user_code_index EQ 0xff) || (curr_user_code_index EQ max_num_user_codes -1)) + curr_user_code_index = 0; + else + curr_user_code_index++; + + if(num_user_codes < max_num_user_codes) + num_user_codes++; + + memcpy(&((UBYTE *)personalisation_sim->pBody)[index + (curr_user_code_index*NW_NS_MSIN_CODE_LEN)],imsi_field,NW_NS_MSIN_CODE_LEN); + ((UBYTE *)personalisation_sim->pBody)[index - CURR_USER_CODE_INDEX_SIZE] = curr_user_code_index; + ((UBYTE *)personalisation_sim->pBody)[index - CURR_USER_CODE_INDEX_SIZE - NUM_USER_CODE_SIZE] = num_user_codes; + sec_set_REC(type, personalisation_sim); + break; + } +} + +#endif //SIM_PERS + + + +/* + PURPOSE : convert bcd to ASCII + +*/ + +LOCAL void decodeB2A (U8 *bcd, U8 bcd_len, U8 *ascii) +{ + int i; + + TRACE_FUNCTION("decodeB2A()"); + + for (i=0; i<bcd_len*2; i++) + { + ascii[i] = (i & 1) ? (bcd[i/2]>>4)+'0' : (bcd[i/2]&0x0f)+'0'; + if (ascii[i]>'9') + break; /* stop if invalid digit */ + } + ascii[i] = 0; +} + +LOCAL void encodeA2B (char *ascii, UBYTE *bcd, UBYTE bcd_len) +{ + UBYTE i; + UBYTE digit; + + TRACE_FUNCTION("encodeA2B()"); + + for (i=0; i<bcd_len*2; i++) /* fill the whole field, pad remaining with 0xf */ + { + if (i<strlen(ascii)) + { + digit = ascii[i]; + if (digit >= '0' OR digit <= '9') + { + digit-= '0'; + } + else + { + TRACE_EVENT_P1("[WRN] invalid digit in PIN \"%d\", skipping!", digit); + digit = 0x0f; + } + } + else + { + digit = 0x0f; /* unused nibbles are set to 'F'. */ + } + + if ((i & 1) EQ 0) + { + /* process PIN digit 1,3,5,... at i=0,2,4,...*/ + bcd[i/2] = digit; + } + else + { + /* process PIN digit 2,4,6,... at i=1,3,5,...*/ + bcd[i/2] |= digit << 4; + } + } +} + +/* That is a workaround to buld simulation test cases */ +#ifdef _SIMULATION_ + #define effs_t int + #define EFFS_OK 0 + #define FFS_fread(a, b, c) 0 + #define FFS_fwrite(a, b, c) 0 +#endif /*_SIMULATION_*/ + +#define FFS_MMILOCK_STATUS "/gsm/MELOCK/SecCode" + +/* ++------------------------------------------------------------------------------ +| Function : aci_ext_personalisation_CS_get_status ++------------------------------------------------------------------------------ +| Description : Reads value of CS lock from file and returns it +| Parameters : void +| +| +| Return : status of CS lock +| Remark: : It is proposed to implement through security driver +| ++------------------------------------------------------------------------------ +*/ +T_SIMLOCK_STATUS aci_ext_personalisation_CS_get_status() +{ + effs_t ffs_rslt; + TRACE_FUNCTION("aci_ext_personalisation_CS_get_status()"); + + ffs_rslt = FFS_fread(FFS_MMILOCK_STATUS, &MMI_personalisation_status, sizeof(MMI_personalisation_status)); + if(ffs_rslt < EFFS_OK) /* error */ + { + TRACE_EVENT_P1("unable to read %s", FFS_MMILOCK_STATUS); + return SIMLOCK_FAIL; + } + return (T_SIMLOCK_STATUS) MMI_personalisation_status.State; +} + + +/* ++------------------------------------------------------------------------------ +| Function : aci_ext_personalisation_CS_set_status ++------------------------------------------------------------------------------ +| Description : Reads value of CS lock from file compare passwords and if correct, sets CS lock status +| Parameters : lock - enable or disable +| passwd - password to change lock +| +| +| Return : status of operation +| Remark: : It is proposed to implement through security driver +| ++------------------------------------------------------------------------------ +*/ +T_SIMLOCK_STATUS aci_ext_personalisation_CS_set_status(T_SIMLOCK_STATUS lock , char * passwd) +{ + effs_t ffs_rslt; + U8 exp_pin[6+1]; /* +1 for '\0' */ + T_SIMLOCK_STATUS result; + TRACE_FUNCTION("aci_ext_personalisation_CS_set_status()"); + + /* Read data from FFS */ + + ffs_rslt = FFS_fread(FFS_MMILOCK_STATUS, &MMI_personalisation_status, sizeof(MMI_personalisation_status)); + + if(ffs_rslt < EFFS_OK) /* error */ + { + TRACE_EVENT_P1("unable to read %s", FFS_MMILOCK_STATUS); + return SIMLOCK_FAIL; + } + + decodeB2A(MMI_personalisation_status.Cur_code, 3, exp_pin); + + if (strncmp((char *)exp_pin, (char *)passwd, 3)) + { + /* Block personalisation lock, if tried too often! */ + MMI_personalisation_status.cnt++; + if (MMI_personalisation_status.cnt >= MMI_personalisation_status.maxcnt) + { + result = SIMLOCK_BLOCKED; + } + else + { + result = SIMLOCK_LOCKED; + } + } + else + { + /* correct pin passed */ + MMI_personalisation_status.cnt = 0; + MMI_personalisation_status.State = lock; + result = lock; + } + ffs_rslt = FFS_fwrite(FFS_MMILOCK_STATUS, &MMI_personalisation_status, sizeof(MMI_personalisation_status)); + + if (ffs_rslt < EFFS_OK) + { + TRACE_EVENT_P1("unable to write %s", FFS_MMILOCK_STATUS); + return SIMLOCK_FAIL; + } + return result; +} + +/* ++------------------------------------------------------------------------------ +| Function : aci_ext_personalisation_CS_change_password ++------------------------------------------------------------------------------ +| Description : Reads value of CS lock from file compare passwords and if correct, sets new password +| Parameters : passwd - old password +| new_passwd - new password +| +| +| Return : status of operation +| Remark: : It is proposed to implement through security driver +| ++------------------------------------------------------------------------------ +*/ +T_SIMLOCK_STATUS aci_ext_personalisation_CS_change_password( char *passwd, char *new_passwd ) +{ + effs_t ffs_rslt; + U8 exp_pin[6+1]; /* +1 for '\0' */ + T_SIMLOCK_STATUS result; + + TRACE_FUNCTION("aci_ext_personalisation_CS_change_password()"); + + ffs_rslt = FFS_fread(FFS_MMILOCK_STATUS, &MMI_personalisation_status, sizeof(MMI_personalisation_status)); + if(ffs_rslt < EFFS_OK) /* error */ + { + TRACE_EVENT_P1("unable to read %s", FFS_MMILOCK_STATUS); + return SIMLOCK_FAIL; + } + + + decodeB2A(MMI_personalisation_status.Cur_code, 3, exp_pin); + + if (strncmp((char *)exp_pin, (char *)passwd, 3)) + { + /* Block personalisation lock, if tried too often! */ + MMI_personalisation_status.cnt++; + if (MMI_personalisation_status.cnt >= MMI_personalisation_status.maxcnt) + { + result = SIMLOCK_BLOCKED; + } + else + { + result = SIMLOCK_LOCKED; + } + } + else + { + /* correct pin passed */ + MMI_personalisation_status.cnt=0; + if ((new_passwd NEQ NULL) AND (strlen(new_passwd) > 0)) + { + encodeA2B(new_passwd, MMI_personalisation_status.Cur_code, 3); + } + result = (T_SIMLOCK_STATUS) MMI_personalisation_status.State; + } + ffs_rslt = FFS_fwrite(FFS_MMILOCK_STATUS, &MMI_personalisation_status, sizeof(MMI_personalisation_status)); + + if (ffs_rslt < EFFS_OK) + { + TRACE_EVENT_P1("unable to write %s", FFS_MMILOCK_STATUS); + return SIMLOCK_FAIL; + } + return result; +} + +