Analysis of SIMLock and simlock Functions
I. background
The lock card is SIMLock. When the mobile phone is started or SIM card is inserted, the configuration information preset in NV on the modem side of the mobile phone will be compared with the information in the SIM card to check whether it matches. If yes, the SIM card can be used normally. If they do not match, SIM card functions cannot be used normally, such as making phone calls, sending text messages, and surfing the Internet. Alternatively, you can only register a 2G network but not a 4G network.
Objective: Some carriers require to control the use of a certain type of card to protect their own interests (the carrier customizes the machine)
Like the SIMLock and pattern lock, digital lock, PIN lock, and PUK lock, it is a lock in the Keyguard module.
Ii. Card lock requirements
There are seven types of locks required, including NP locks, NS locks, CP locks, and SP locks.
From the perspective of Android machines, SP locks (MCC/MNC) are currently the most commonly used. This article describes the process of parsing the SP locks.
Iii. Analysis of the lock Process
1. Check and compare the configuration information of the SIM card on the modem side. If the SIM card is matched, the SIM card will be loaded. If the SIM card does not match, the lock information will be reported.
2. the RIL layer detects the lock information reported by the modem and sends it to the framework layer. Finally, the AP layer monitors the event:
3. The lock card interface is displayed on the AP layer, requiring users to enter the unlock code to unlock
Iv. Flowchart
1. Lock Flowchart
2. Unlock Flowchart
V. Code Parsing
The MTK platform already supports the SIMLock function, but it can only write fixed MCC/MNC in the Code and cannot be flexibly configured. That is, a set of codes can correspond to only one set of corresponding lock card configuration information. For mobile phone manufacturers, it obviously does not meet the requirements. The shipping countries all over the world, the lock card configuration information is different, and too many code versions cannot be managed, therefore, we must discard the SIMLock feature of MTK.
(1) modem-side Customization
Involved code files:
custom/modem/common/ps/custom_nvram_extra.c custom/modem/common/ps/customer_at_command.c custom/service/nvram/custom_nvram_sec.c custom/service/nvram/custom_nvram_sec.h interface/service/nvram/nvram_data_items.h service/nvram/src/nvram_factory_config.c service/nvram/src/nvram_main.c
A. Number of extended lock card configuration information groups
Custom_nvram_sec.h
# Define SML_MAX_SUPPORT_CAT_N 50
When initializing an array, you need to add the corresponding default configuration information
const nvram_sml_context_struct NVRAM_EF_SML_DEFAULT = {SML_MAGIC_HEAD_VALUE, {{SML_STATE_UNLOCK,SML_RETRY_COUNT_N_CAT,0,0}, /* Category N */{SML_STATE_UNLOCK,SML_RETRY_COUNT_NS_CAT ,0,0}, /* Category NS */{SML_STATE_UNLOCK,SML_RETRY_COUNT_SP_CAT ,0,0}, /* Category SP */{SML_STATE_UNLOCK,SML_RETRY_COUNT_C_CAT ,0,0}, /* Category C */{SML_STATE_UNLOCK,SML_RETRY_COUNT_SIM_CAT ,0,0}, /* Category SIM */{SML_STATE_UNLOCK,SML_RETRY_COUNT_NS_CAT ,0,0}, /* Link NS-SP */{SML_STATE_UNLOCK,SML_RETRY_COUNT_C_CAT ,0,0}}, /* Link SIM-C */{{SML_KEY_SET,{0x21,0x43,0x65,0x87,0xFF,0xFF,0xFF,0xFF}},{SML_KEY_SET,{0x65,0x87,0x21,0x43,0xFF,0xFF,0xFF,0xFF}},{SML_KEY_SET,{0x11,0x22,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}},{SML_KEY_EMPTY,{0x33,0x44,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}},{SML_KEY_EMPTY,{0x55,0x66,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}},{SML_KEY_SET,{0x77,0x88,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}},{SML_KEY_SET,{0x99,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}}},/* Category N code */{0x73,0x00,0x1F,0x73,0x00,0x2F,0x73,0x00,0x3F,0x73,0x00,0x4F,0x73,0x00,0x5F, 0x73,0x00,0x6F,0x73,0x00,0x7F,0x73,0x00,0x8F,0x73,0x00,0x9F,0x73,0x01,0x0F, 0x73,0x01,0x1F,0x73,0x09,0x9F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00},/* Category NS code */{0xc2,0xc2,0xc2,0xc2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00},/* Category SP code */{0xc3,0xc3,0xc3,0xc3,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00},/* Category C code */{0xc4,0xc4,0xc4,0xc4,0xc4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00},/* Category SIM code */{0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/* Link Category NS-SP */{0xc6,0xc6,0xc6,0xc6,0xc6,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00}, /* Link Category SIM-C */{0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},{0xFF,0xFF},SML_MAGIC_TAIL_VALUE};
B. Modify the remaining unlock times
Custom_nvram_sec.h
# Define SML_MAX_RETRY_COUNT 10
C. Extended custom lock card NV item
For example, you can use tools to view and modify the NV of the MTK source lock card, so that the lock card is easily cracked. Custom lock NV items, even if the MTK source is cracked, The SIMLock function still works normally.
However, in Android 6.0, MTK has already been processed on the modem side. You cannot view and modify the NV item using the tool.
(1) define NV items first
(2) initialize the corresponding NV item. Refer to the source code.
D. Special requirements for extended locks (associated locks, etc)
Because the source AT command cannot query the lock card status information, you can extend the AT command to implement
The following code is an extended AT + QSIM1 command. The query information includes the lock card status, lock card configuration information, and the number of remaining times.
if (strcmp(cmd_name, "QSIM1") == 0) { extern void simlock_query_sml_info(kal_uint8 sim_id, sml_context_struct* sml_static_buffer);char info_buffer[MAX_UART_LEN+1];int NumOfPlmn,i; int isLocked = -1;sml_context_struct sml_static_buffer;memset(&sml_static_buffer,0x00,sizeof(sml_context_struct)); simlock_query_sml_info(1, &sml_static_buffer);kal_prompt_trace(MOD_SIM, "[sim1]: receive full_cmd_string =%s", full_cmd_string);sml_cat_enum cat = 0xff;for(cat = SML_CAT_N; cat < SML_CAT_SIZE; cat++) { if(sml_static_buffer.cat[cat].state == 0x01) { isLocked = 1; break; } } if(isLocked == 1) { NumOfPlmn = sml_static_buffer.cat[cat].num;NumOfPlmn = 1; sprintf(info_buffer, "+QSIM1:%02x;",sml_static_buffer.cat[cat].state); sprintf(info_buffer+strlen(info_buffer), "%02x;",NumOfPlmn); //#define SML_SIZE_OF_CAT_N 3 /* MCC/MNC */ //#define SML_SIZE_OF_CAT_NS 4 /* MCC/MNC + HLR */ //#define SML_SIZE_OF_CAT_SP 4 /* MCC/MNC + GID1 */ //#define SML_SIZE_OF_CAT_C 5 /* MCC/MNC + GID1 + GID2 */ //#define SML_SIZE_OF_CAT_SIM 8 /* IMSI */ //#define SML_SIZE_OF_LINK_NS_SP 5 /* MCC/MNC + HLR+ GID1 */ //#define SML_SIZE_OF_LINK_SIM_C 10 /* IMSI + GID1 + GID2 */ if(cat == SML_CAT_N) { for(i = 0; i < NumOfPlmn*SML_SIZE_OF_CAT_N; i=i+SML_SIZE_OF_CAT_N) { sprintf(info_buffer+strlen(info_buffer), "%02x%02x%02x;",sml_static_buffer.code_cat_n[i], sml_static_buffer.code_cat_n[i + 1],sml_static_buffer.code_cat_n[i + 2]); } //sprintf(info_buffer+strlen(info_buffer), "%02x%02x%02x%02x",sml_static_buffer.key[cat].key[4], // sml_static_buffer.key[cat].key[5],sml_static_buffer.key[cat].key[6],sml_static_buffer.key[cat].key[7]); //kal_prompt_trace(MOD_SIM, " receive cmd =%s ; flag is %x ", cmd_name, read_buffer); } else if(cat == SML_CAT_NS) { for(i = 0; i < NumOfPlmn*SML_SIZE_OF_CAT_NS; i=i+SML_SIZE_OF_CAT_NS) { sprintf(info_buffer+strlen(info_buffer), "%02x%02x%02x%02x;",sml_static_buffer.code_cat_ns[i], sml_static_buffer.code_cat_ns[i + 1],sml_static_buffer.code_cat_ns[i + 2],sml_static_buffer.code_cat_ns[i + 3]); } } else if(cat == SML_CAT_SP) { for(i = 0; i < NumOfPlmn*SML_SIZE_OF_CAT_SP; i=i+SML_SIZE_OF_CAT_SP) { sprintf(info_buffer+strlen(info_buffer), "%02x%02x%02x%02x;",sml_static_buffer.code_cat_sp[i], sml_static_buffer.code_cat_sp[i + 1],sml_static_buffer.code_cat_sp[i + 2],sml_static_buffer.code_cat_sp[i + 3]); } } else if(cat == SML_CAT_C) { for(i = 0; i < NumOfPlmn*SML_SIZE_OF_CAT_C; i=i+SML_SIZE_OF_CAT_C) { sprintf(info_buffer+strlen(info_buffer), "%02x%02x%02x%02x",sml_static_buffer.code_cat_c[i], sml_static_buffer.code_cat_c[i + 1],sml_static_buffer.code_cat_c[i + 2],sml_static_buffer.code_cat_c[i + 3]); sprintf(info_buffer+strlen(info_buffer), "%02x;",sml_static_buffer.code_cat_c[i + 4]); } } else if(cat == SML_CAT_SIM) { for(i = 0; i < NumOfPlmn*SML_SIZE_OF_CAT_SIM; i=i+SML_SIZE_OF_CAT_SIM) { sprintf(info_buffer+strlen(info_buffer), "%02x%02x%02x%02x",sml_static_buffer.code_cat_sim[i], sml_static_buffer.code_cat_sim[i + 1],sml_static_buffer.code_cat_sim[i + 2],sml_static_buffer.code_cat_sim[i + 3]); sprintf(info_buffer+strlen(info_buffer), "%02x%02x%02x%02x;",sml_static_buffer.code_cat_sim[i + 4], sml_static_buffer.code_cat_sim[i + 5],sml_static_buffer.code_cat_sim[i + 6], sml_static_buffer.code_cat_sim[i + 7]); } } else if(cat == SML_CAT_NS_SP) { for(i = 0; i < NumOfPlmn*SML_SIZE_OF_LINK_NS_SP; i=i+SML_SIZE_OF_LINK_NS_SP) { sprintf(info_buffer+strlen(info_buffer), "%02x%02x%02x%02x",sml_static_buffer.code_cat_ns_sp[i], sml_static_buffer.code_cat_ns_sp[i + 1],sml_static_buffer.code_cat_ns_sp[i + 2],sml_static_buffer.code_cat_ns_sp[i + 3]); sprintf(info_buffer+strlen(info_buffer), "%02x;",sml_static_buffer.code_cat_ns_sp[i + 4]); } } else if(cat == SML_CAT_SIM_C) { for(i = 0; i < NumOfPlmn*SML_SIZE_OF_LINK_SIM_C; i=i+SML_SIZE_OF_LINK_SIM_C) { sprintf(info_buffer+strlen(info_buffer), "%02x%02x%02x%02x",sml_static_buffer.code_cat_sim_c[i], sml_static_buffer.code_cat_sim_c[i + 1],sml_static_buffer.code_cat_sim_c[i + 2], sml_static_buffer.code_cat_sim_c[i + 3]); sprintf(info_buffer+strlen(info_buffer), "%02x%02x%02x%02x",sml_static_buffer.code_cat_sim_c[i + 4], sml_static_buffer.code_cat_sim_c[i + 5],sml_static_buffer.code_cat_sim_c[i + 6], sml_static_buffer.code_cat_sim_c[i + 7]); sprintf(info_buffer+strlen(info_buffer), "%02x%02x;",sml_static_buffer.code_cat_sim_c[i + 8], sml_static_buffer.code_cat_sim_c[i + 9]); } } sprintf(info_buffer+strlen(info_buffer), "%02x%02x%02x%02x",sml_static_buffer.key[cat].key[0], sml_static_buffer.key[cat].key[1],sml_static_buffer.key[cat].key[2],sml_static_buffer.key[cat].key[3]); sprintf(info_buffer+strlen(info_buffer), "%02x%02x%02x%02x;",sml_static_buffer.key[cat].key[4], sml_static_buffer.key[cat].key[5],sml_static_buffer.key[cat].key[6],sml_static_buffer.key[cat].key[7]); sprintf(info_buffer+strlen(info_buffer), "%02x;",sml_static_buffer.cat[cat].retry_count); sprintf(info_buffer+strlen(info_buffer), "%02x;",cat); } else { sprintf(info_buffer, "+QSIM1:%02x;",0x00); }//kal_prompt_trace(MOD_NVRAM, "[sim1]: info_buffer is === >> %s", info_buffer);rmmi_write_to_uart((kal_uint8*)info_buffer, strlen(info_buffer), KAL_FALSE);sprintf(buffer, "OK");rmmi_write_to_uart((kal_uint8*)buffer, strlen(buffer), KAL_TRUE);return KAL_TRUE; }
(2) customization of the AP side
The SIMLock customization workload is mainly concentrated on the modem side, and the AP side mainly displays the interface and AT command interaction.
A. AT command Interaction
Query SIM card status
Query the status information of the lock card: whether to lock the card, the configuration information of the lock card (MCC/MNC), and the remaining unlock times.
Send the PASSWORD to the RIL side to parse the returned information for successful unlocking.
B. display on the user interface
Prompt the user to enter the unlock code
Number of remaining unlocking times prompted
Prompt that the unlock code can be entered for the remaining time
Prompt that the SIM card is permanently locked