Support reseting iCx cards (#2451)
* Support reseting iCx cards * add submenu * Fix auth * switch key derivation to use same method * test system keys using both elite and standard kdf Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
		
							parent
							
								
									9dd1fb64b7
								
							
						
					
					
						commit
						eefca9f498
					
				| @ -7,6 +7,9 @@ | |||||||
| const uint8_t picopass_iclass_key[] = {0xaf, 0xa7, 0x85, 0xa7, 0xda, 0xb3, 0x33, 0x78}; | const uint8_t picopass_iclass_key[] = {0xaf, 0xa7, 0x85, 0xa7, 0xda, 0xb3, 0x33, 0x78}; | ||||||
| const uint8_t picopass_factory_credit_key[] = {0x76, 0x65, 0x54, 0x43, 0x32, 0x21, 0x10, 0x00}; | const uint8_t picopass_factory_credit_key[] = {0x76, 0x65, 0x54, 0x43, 0x32, 0x21, 0x10, 0x00}; | ||||||
| const uint8_t picopass_factory_debit_key[] = {0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87}; | const uint8_t picopass_factory_debit_key[] = {0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87}; | ||||||
|  | const uint8_t picopass_xice_key[] = {0x20, 0x20, 0x66, 0x66, 0x66, 0x66, 0x88, 0x88}; | ||||||
|  | const uint8_t picopass_xicl_key[] = {0x20, 0x20, 0x66, 0x66, 0x66, 0x66, 0x88, 0x88}; | ||||||
|  | const uint8_t picopass_xics_key[] = {0x66, 0x66, 0x20, 0x20, 0x66, 0x66, 0x88, 0x88}; | ||||||
| 
 | 
 | ||||||
| static void picopass_worker_enable_field() { | static void picopass_worker_enable_field() { | ||||||
|     furi_hal_nfc_ll_txrx_on(); |     furi_hal_nfc_ll_txrx_on(); | ||||||
| @ -192,7 +195,7 @@ static ReturnCode picopass_auth_standard(uint8_t* csn, uint8_t* div_key) { | |||||||
|     } |     } | ||||||
|     memcpy(ccnr, rcRes.CCNR, sizeof(rcRes.CCNR)); // last 4 bytes left 0
 |     memcpy(ccnr, rcRes.CCNR, sizeof(rcRes.CCNR)); // last 4 bytes left 0
 | ||||||
| 
 | 
 | ||||||
|     loclass_diversifyKey(csn, picopass_iclass_key, div_key); |     loclass_iclass_calc_div_key(csn, (uint8_t*)picopass_iclass_key, div_key, false); | ||||||
|     loclass_opt_doReaderMAC(ccnr, div_key, mac); |     loclass_opt_doReaderMAC(ccnr, div_key, mac); | ||||||
| 
 | 
 | ||||||
|     return rfalPicoPassPollerCheck(mac, &chkRes); |     return rfalPicoPassPollerCheck(mac, &chkRes); | ||||||
| @ -214,7 +217,7 @@ static ReturnCode picopass_auth_factory(uint8_t* csn, uint8_t* div_key) { | |||||||
|     } |     } | ||||||
|     memcpy(ccnr, rcRes.CCNR, sizeof(rcRes.CCNR)); // last 4 bytes left 0
 |     memcpy(ccnr, rcRes.CCNR, sizeof(rcRes.CCNR)); // last 4 bytes left 0
 | ||||||
| 
 | 
 | ||||||
|     loclass_diversifyKey(csn, picopass_factory_debit_key, div_key); |     loclass_iclass_calc_div_key(csn, (uint8_t*)picopass_factory_debit_key, div_key, false); | ||||||
|     loclass_opt_doReaderMAC(ccnr, div_key, mac); |     loclass_opt_doReaderMAC(ccnr, div_key, mac); | ||||||
| 
 | 
 | ||||||
|     return rfalPicoPassPollerCheck(mac, &chkRes); |     return rfalPicoPassPollerCheck(mac, &chkRes); | ||||||
| @ -224,7 +227,8 @@ static ReturnCode picopass_auth_dict( | |||||||
|     uint8_t* csn, |     uint8_t* csn, | ||||||
|     PicopassPacs* pacs, |     PicopassPacs* pacs, | ||||||
|     uint8_t* div_key, |     uint8_t* div_key, | ||||||
|     IclassEliteDictType dict_type) { |     IclassEliteDictType dict_type, | ||||||
|  |     bool elite) { | ||||||
|     rfalPicoPassReadCheckRes rcRes; |     rfalPicoPassReadCheckRes rcRes; | ||||||
|     rfalPicoPassCheckRes chkRes; |     rfalPicoPassCheckRes chkRes; | ||||||
| 
 | 
 | ||||||
| @ -269,7 +273,7 @@ static ReturnCode picopass_auth_dict( | |||||||
|         } |         } | ||||||
|         memcpy(ccnr, rcRes.CCNR, sizeof(rcRes.CCNR)); // last 4 bytes left 0
 |         memcpy(ccnr, rcRes.CCNR, sizeof(rcRes.CCNR)); // last 4 bytes left 0
 | ||||||
| 
 | 
 | ||||||
|         loclass_iclass_calc_div_key(csn, key, div_key, true); |         loclass_iclass_calc_div_key(csn, key, div_key, elite); | ||||||
|         loclass_opt_doReaderMAC(ccnr, div_key, mac); |         loclass_opt_doReaderMAC(ccnr, div_key, mac); | ||||||
| 
 | 
 | ||||||
|         err = rfalPicoPassPollerCheck(mac, &chkRes); |         err = rfalPicoPassPollerCheck(mac, &chkRes); | ||||||
| @ -303,22 +307,35 @@ ReturnCode picopass_auth(PicopassBlock* AA1, PicopassPacs* pacs) { | |||||||
|         return ERR_NONE; |         return ERR_NONE; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     FURI_LOG_I(TAG, "Starting user dictionary attack"); |     FURI_LOG_I(TAG, "Starting user dictionary attack [Elite KDF]"); | ||||||
|     err = picopass_auth_dict( |     err = picopass_auth_dict( | ||||||
|         AA1[PICOPASS_CSN_BLOCK_INDEX].data, |         AA1[PICOPASS_CSN_BLOCK_INDEX].data, | ||||||
|         pacs, |         pacs, | ||||||
|         AA1[PICOPASS_KD_BLOCK_INDEX].data, |         AA1[PICOPASS_KD_BLOCK_INDEX].data, | ||||||
|         IclassEliteDictTypeUser); |         IclassEliteDictTypeUser, | ||||||
|  |         true); | ||||||
|     if(err == ERR_NONE) { |     if(err == ERR_NONE) { | ||||||
|         return ERR_NONE; |         return ERR_NONE; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     FURI_LOG_I(TAG, "Starting system dictionary attack"); |     FURI_LOG_I(TAG, "Starting system dictionary attack [Elite KDF]"); | ||||||
|     err = picopass_auth_dict( |     err = picopass_auth_dict( | ||||||
|         AA1[PICOPASS_CSN_BLOCK_INDEX].data, |         AA1[PICOPASS_CSN_BLOCK_INDEX].data, | ||||||
|         pacs, |         pacs, | ||||||
|         AA1[PICOPASS_KD_BLOCK_INDEX].data, |         AA1[PICOPASS_KD_BLOCK_INDEX].data, | ||||||
|         IclassEliteDictTypeFlipper); |         IclassEliteDictTypeFlipper, | ||||||
|  |         true); | ||||||
|  |     if(err == ERR_NONE) { | ||||||
|  |         return ERR_NONE; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     FURI_LOG_I(TAG, "Starting system dictionary attack [Standard KDF]"); | ||||||
|  |     err = picopass_auth_dict( | ||||||
|  |         AA1[PICOPASS_CSN_BLOCK_INDEX].data, | ||||||
|  |         pacs, | ||||||
|  |         AA1[PICOPASS_KD_BLOCK_INDEX].data, | ||||||
|  |         IclassEliteDictTypeFlipper, | ||||||
|  |         false); | ||||||
|     if(err == ERR_NONE) { |     if(err == ERR_NONE) { | ||||||
|         return ERR_NONE; |         return ERR_NONE; | ||||||
|     } |     } | ||||||
| @ -396,7 +413,7 @@ ReturnCode picopass_write_card(PicopassBlock* AA1) { | |||||||
|     } |     } | ||||||
|     memcpy(ccnr, rcRes.CCNR, sizeof(rcRes.CCNR)); // last 4 bytes left 0
 |     memcpy(ccnr, rcRes.CCNR, sizeof(rcRes.CCNR)); // last 4 bytes left 0
 | ||||||
| 
 | 
 | ||||||
|     loclass_diversifyKey(selRes.CSN, picopass_iclass_key, div_key); |     loclass_iclass_calc_div_key(selRes.CSN, (uint8_t*)picopass_iclass_key, div_key, false); | ||||||
|     loclass_opt_doReaderMAC(ccnr, div_key, mac); |     loclass_opt_doReaderMAC(ccnr, div_key, mac); | ||||||
| 
 | 
 | ||||||
|     err = rfalPicoPassPollerCheck(mac, &chkRes); |     err = rfalPicoPassPollerCheck(mac, &chkRes); | ||||||
| @ -438,7 +455,7 @@ ReturnCode picopass_write_card(PicopassBlock* AA1) { | |||||||
|     return ERR_NONE; |     return ERR_NONE; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ReturnCode picopass_write_block(PicopassPacs* pacs, uint8_t blockNo, uint8_t* newBlock) { | ReturnCode picopass_write_block(PicopassBlock* AA1, uint8_t blockNo, uint8_t* newBlock) { | ||||||
|     rfalPicoPassIdentifyRes idRes; |     rfalPicoPassIdentifyRes idRes; | ||||||
|     rfalPicoPassSelectRes selRes; |     rfalPicoPassSelectRes selRes; | ||||||
|     rfalPicoPassReadCheckRes rcRes; |     rfalPicoPassReadCheckRes rcRes; | ||||||
| @ -446,7 +463,6 @@ ReturnCode picopass_write_block(PicopassPacs* pacs, uint8_t blockNo, uint8_t* ne | |||||||
| 
 | 
 | ||||||
|     ReturnCode err; |     ReturnCode err; | ||||||
| 
 | 
 | ||||||
|     uint8_t div_key[8] = {0}; |  | ||||||
|     uint8_t mac[4] = {0}; |     uint8_t mac[4] = {0}; | ||||||
|     uint8_t ccnr[12] = {0}; |     uint8_t ccnr[12] = {0}; | ||||||
| 
 | 
 | ||||||
| @ -469,9 +485,12 @@ ReturnCode picopass_write_block(PicopassPacs* pacs, uint8_t blockNo, uint8_t* ne | |||||||
|     } |     } | ||||||
|     memcpy(ccnr, rcRes.CCNR, sizeof(rcRes.CCNR)); // last 4 bytes left 0
 |     memcpy(ccnr, rcRes.CCNR, sizeof(rcRes.CCNR)); // last 4 bytes left 0
 | ||||||
| 
 | 
 | ||||||
|     loclass_diversifyKey(selRes.CSN, pacs->key, div_key); |     if(memcmp(selRes.CSN, AA1[PICOPASS_CSN_BLOCK_INDEX].data, PICOPASS_BLOCK_LEN) != 0) { | ||||||
|     loclass_opt_doReaderMAC(ccnr, div_key, mac); |         FURI_LOG_E(TAG, "Wrong CSN for write"); | ||||||
|  |         return ERR_REQUEST; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|  |     loclass_opt_doReaderMAC(ccnr, AA1[PICOPASS_KD_BLOCK_INDEX].data, mac); | ||||||
|     err = rfalPicoPassPollerCheck(mac, &chkRes); |     err = rfalPicoPassPollerCheck(mac, &chkRes); | ||||||
|     if(err != ERR_NONE) { |     if(err != ERR_NONE) { | ||||||
|         FURI_LOG_E(TAG, "rfalPicoPassPollerCheck error %d", err); |         FURI_LOG_E(TAG, "rfalPicoPassPollerCheck error %d", err); | ||||||
| @ -489,7 +508,7 @@ ReturnCode picopass_write_block(PicopassPacs* pacs, uint8_t blockNo, uint8_t* ne | |||||||
|         newBlock[5], |         newBlock[5], | ||||||
|         newBlock[6], |         newBlock[6], | ||||||
|         newBlock[7]}; |         newBlock[7]}; | ||||||
|     loclass_doMAC_N(data, sizeof(data), div_key, mac); |     loclass_doMAC_N(data, sizeof(data), AA1[PICOPASS_KD_BLOCK_INDEX].data, mac); | ||||||
|     FURI_LOG_D( |     FURI_LOG_D( | ||||||
|         TAG, |         TAG, | ||||||
|         "loclass_doMAC_N %d %02x%02x%02x%02x%02x%02x%02x%02x %02x%02x%02x%02x", |         "loclass_doMAC_N %d %02x%02x%02x%02x%02x%02x%02x%02x %02x%02x%02x%02x", | ||||||
| @ -524,8 +543,8 @@ int32_t picopass_worker_task(void* context) { | |||||||
|         picopass_worker_detect(picopass_worker); |         picopass_worker_detect(picopass_worker); | ||||||
|     } else if(picopass_worker->state == PicopassWorkerStateWrite) { |     } else if(picopass_worker->state == PicopassWorkerStateWrite) { | ||||||
|         picopass_worker_write(picopass_worker); |         picopass_worker_write(picopass_worker); | ||||||
|     } else if(picopass_worker->state == PicopassWorkerStateWriteStandardKey) { |     } else if(picopass_worker->state == PicopassWorkerStateWriteKey) { | ||||||
|         picopass_worker_write_standard_key(picopass_worker); |         picopass_worker_write_key(picopass_worker); | ||||||
|     } |     } | ||||||
|     picopass_worker_disable_field(ERR_NONE); |     picopass_worker_disable_field(ERR_NONE); | ||||||
| 
 | 
 | ||||||
| @ -633,7 +652,7 @@ void picopass_worker_write(PicopassWorker* picopass_worker) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void picopass_worker_write_standard_key(PicopassWorker* picopass_worker) { | void picopass_worker_write_key(PicopassWorker* picopass_worker) { | ||||||
|     PicopassDeviceData* dev_data = picopass_worker->dev_data; |     PicopassDeviceData* dev_data = picopass_worker->dev_data; | ||||||
|     PicopassBlock* AA1 = dev_data->AA1; |     PicopassBlock* AA1 = dev_data->AA1; | ||||||
|     PicopassPacs* pacs = &dev_data->pacs; |     PicopassPacs* pacs = &dev_data->pacs; | ||||||
| @ -646,7 +665,7 @@ void picopass_worker_write_standard_key(PicopassWorker* picopass_worker) { | |||||||
|     uint8_t* oldKey = AA1[PICOPASS_KD_BLOCK_INDEX].data; |     uint8_t* oldKey = AA1[PICOPASS_KD_BLOCK_INDEX].data; | ||||||
| 
 | 
 | ||||||
|     uint8_t newKey[PICOPASS_BLOCK_LEN] = {0}; |     uint8_t newKey[PICOPASS_BLOCK_LEN] = {0}; | ||||||
|     loclass_diversifyKey(csn, picopass_iclass_key, newKey); |     loclass_iclass_calc_div_key(csn, pacs->key, newKey, false); | ||||||
| 
 | 
 | ||||||
|     if((fuses & 0x80) == 0x80) { |     if((fuses & 0x80) == 0x80) { | ||||||
|         FURI_LOG_D(TAG, "Plain write for personalized mode key change"); |         FURI_LOG_D(TAG, "Plain write for personalized mode key change"); | ||||||
| @ -658,9 +677,9 @@ void picopass_worker_write_standard_key(PicopassWorker* picopass_worker) { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     while(picopass_worker->state == PicopassWorkerStateWriteStandardKey) { |     while(picopass_worker->state == PicopassWorkerStateWriteKey) { | ||||||
|         if(picopass_detect_card(1000) == ERR_NONE) { |         if(picopass_detect_card(1000) == ERR_NONE) { | ||||||
|             err = picopass_write_block(pacs, PICOPASS_KD_BLOCK_INDEX, newKey); |             err = picopass_write_block(AA1, PICOPASS_KD_BLOCK_INDEX, newKey); | ||||||
|             if(err != ERR_NONE) { |             if(err != ERR_NONE) { | ||||||
|                 FURI_LOG_E(TAG, "picopass_write_block error %d", err); |                 FURI_LOG_E(TAG, "picopass_write_block error %d", err); | ||||||
|                 nextState = PicopassWorkerEventFail; |                 nextState = PicopassWorkerEventFail; | ||||||
|  | |||||||
| @ -12,7 +12,7 @@ typedef enum { | |||||||
|     // Main worker states
 |     // Main worker states
 | ||||||
|     PicopassWorkerStateDetect, |     PicopassWorkerStateDetect, | ||||||
|     PicopassWorkerStateWrite, |     PicopassWorkerStateWrite, | ||||||
|     PicopassWorkerStateWriteStandardKey, |     PicopassWorkerStateWriteKey, | ||||||
|     // Transition
 |     // Transition
 | ||||||
|     PicopassWorkerStateStop, |     PicopassWorkerStateStop, | ||||||
| } PicopassWorkerState; | } PicopassWorkerState; | ||||||
|  | |||||||
| @ -31,4 +31,4 @@ int32_t picopass_worker_task(void* context); | |||||||
| 
 | 
 | ||||||
| void picopass_worker_detect(PicopassWorker* picopass_worker); | void picopass_worker_detect(PicopassWorker* picopass_worker); | ||||||
| void picopass_worker_write(PicopassWorker* picopass_worker); | void picopass_worker_write(PicopassWorker* picopass_worker); | ||||||
| void picopass_worker_write_standard_key(PicopassWorker* picopass_worker); | void picopass_worker_write_key(PicopassWorker* picopass_worker); | ||||||
|  | |||||||
| @ -3,6 +3,7 @@ | |||||||
| enum SubmenuIndex { | enum SubmenuIndex { | ||||||
|     SubmenuIndexSave, |     SubmenuIndexSave, | ||||||
|     SubmenuIndexSaveAsLF, |     SubmenuIndexSaveAsLF, | ||||||
|  |     SubmenuIndexChangeKey, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void picopass_scene_card_menu_submenu_callback(void* context, uint32_t index) { | void picopass_scene_card_menu_submenu_callback(void* context, uint32_t index) { | ||||||
| @ -25,6 +26,13 @@ void picopass_scene_card_menu_on_enter(void* context) { | |||||||
|             picopass_scene_card_menu_submenu_callback, |             picopass_scene_card_menu_submenu_callback, | ||||||
|             picopass); |             picopass); | ||||||
|     } |     } | ||||||
|  |     submenu_add_item( | ||||||
|  |         submenu, | ||||||
|  |         "Change Key", | ||||||
|  |         SubmenuIndexChangeKey, | ||||||
|  |         picopass_scene_card_menu_submenu_callback, | ||||||
|  |         picopass); | ||||||
|  | 
 | ||||||
|     submenu_set_selected_item( |     submenu_set_selected_item( | ||||||
|         picopass->submenu, |         picopass->submenu, | ||||||
|         scene_manager_get_scene_state(picopass->scene_manager, PicopassSceneCardMenu)); |         scene_manager_get_scene_state(picopass->scene_manager, PicopassSceneCardMenu)); | ||||||
| @ -49,6 +57,11 @@ bool picopass_scene_card_menu_on_event(void* context, SceneManagerEvent event) { | |||||||
|             picopass->dev->format = PicopassDeviceSaveFormatLF; |             picopass->dev->format = PicopassDeviceSaveFormatLF; | ||||||
|             scene_manager_next_scene(picopass->scene_manager, PicopassSceneSaveName); |             scene_manager_next_scene(picopass->scene_manager, PicopassSceneSaveName); | ||||||
|             consumed = true; |             consumed = true; | ||||||
|  |         } else if(event.event == SubmenuIndexChangeKey) { | ||||||
|  |             scene_manager_set_scene_state( | ||||||
|  |                 picopass->scene_manager, PicopassSceneCardMenu, SubmenuIndexChangeKey); | ||||||
|  |             scene_manager_next_scene(picopass->scene_manager, PicopassSceneKeyMenu); | ||||||
|  |             consumed = true; | ||||||
|         } |         } | ||||||
|     } else if(event.type == SceneManagerEventTypeBack) { |     } else if(event.type == SceneManagerEventTypeBack) { | ||||||
|         consumed = scene_manager_search_and_switch_to_previous_scene( |         consumed = scene_manager_search_and_switch_to_previous_scene( | ||||||
|  | |||||||
| @ -13,3 +13,4 @@ ADD_SCENE(picopass, write_card, WriteCard) | |||||||
| ADD_SCENE(picopass, write_card_success, WriteCardSuccess) | ADD_SCENE(picopass, write_card_success, WriteCardSuccess) | ||||||
| ADD_SCENE(picopass, read_factory_success, ReadFactorySuccess) | ADD_SCENE(picopass, read_factory_success, ReadFactorySuccess) | ||||||
| ADD_SCENE(picopass, write_key, WriteKey) | ADD_SCENE(picopass, write_key, WriteKey) | ||||||
|  | ADD_SCENE(picopass, key_menu, KeyMenu) | ||||||
|  | |||||||
							
								
								
									
										100
									
								
								applications/plugins/picopass/scenes/picopass_scene_key_menu.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								applications/plugins/picopass/scenes/picopass_scene_key_menu.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,100 @@ | |||||||
|  | #include "../picopass_i.h" | ||||||
|  | 
 | ||||||
|  | enum SubmenuIndex { | ||||||
|  |     SubmenuIndexWriteStandard, | ||||||
|  |     SubmenuIndexWriteiCE, | ||||||
|  |     SubmenuIndexWriteiCL, | ||||||
|  |     SubmenuIndexWriteiCS, | ||||||
|  |     SubmenuIndexWriteCustom, //TODO: user input of key
 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | extern const uint8_t picopass_xice_key[]; | ||||||
|  | extern const uint8_t picopass_xicl_key[]; | ||||||
|  | extern const uint8_t picopass_xics_key[]; | ||||||
|  | extern const uint8_t picopass_iclass_key[]; | ||||||
|  | 
 | ||||||
|  | void picopass_scene_key_menu_submenu_callback(void* context, uint32_t index) { | ||||||
|  |     Picopass* picopass = context; | ||||||
|  | 
 | ||||||
|  |     view_dispatcher_send_custom_event(picopass->view_dispatcher, index); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void picopass_scene_key_menu_on_enter(void* context) { | ||||||
|  |     Picopass* picopass = context; | ||||||
|  |     Submenu* submenu = picopass->submenu; | ||||||
|  | 
 | ||||||
|  |     submenu_add_item( | ||||||
|  |         submenu, | ||||||
|  |         "Write Standard", | ||||||
|  |         SubmenuIndexWriteStandard, | ||||||
|  |         picopass_scene_key_menu_submenu_callback, | ||||||
|  |         picopass); | ||||||
|  |     submenu_add_item( | ||||||
|  |         submenu, | ||||||
|  |         "Write iCE", | ||||||
|  |         SubmenuIndexWriteiCE, | ||||||
|  |         picopass_scene_key_menu_submenu_callback, | ||||||
|  |         picopass); | ||||||
|  |     submenu_add_item( | ||||||
|  |         submenu, | ||||||
|  |         "Write iCL", | ||||||
|  |         SubmenuIndexWriteiCL, | ||||||
|  |         picopass_scene_key_menu_submenu_callback, | ||||||
|  |         picopass); | ||||||
|  |     submenu_add_item( | ||||||
|  |         submenu, | ||||||
|  |         "Write iCS", | ||||||
|  |         SubmenuIndexWriteiCS, | ||||||
|  |         picopass_scene_key_menu_submenu_callback, | ||||||
|  |         picopass); | ||||||
|  | 
 | ||||||
|  |     submenu_set_selected_item( | ||||||
|  |         picopass->submenu, | ||||||
|  |         scene_manager_get_scene_state(picopass->scene_manager, PicopassSceneKeyMenu)); | ||||||
|  | 
 | ||||||
|  |     view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewMenu); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool picopass_scene_key_menu_on_event(void* context, SceneManagerEvent event) { | ||||||
|  |     Picopass* picopass = context; | ||||||
|  |     bool consumed = false; | ||||||
|  | 
 | ||||||
|  |     if(event.type == SceneManagerEventTypeCustom) { | ||||||
|  |         if(event.event == SubmenuIndexWriteStandard) { | ||||||
|  |             scene_manager_set_scene_state( | ||||||
|  |                 picopass->scene_manager, PicopassSceneKeyMenu, SubmenuIndexWriteStandard); | ||||||
|  |             memcpy(picopass->dev->dev_data.pacs.key, picopass_iclass_key, PICOPASS_BLOCK_LEN); | ||||||
|  |             scene_manager_next_scene(picopass->scene_manager, PicopassSceneWriteKey); | ||||||
|  |             consumed = true; | ||||||
|  |         } else if(event.event == SubmenuIndexWriteiCE) { | ||||||
|  |             scene_manager_set_scene_state( | ||||||
|  |                 picopass->scene_manager, PicopassSceneKeyMenu, SubmenuIndexWriteiCE); | ||||||
|  |             memcpy(picopass->dev->dev_data.pacs.key, picopass_xice_key, PICOPASS_BLOCK_LEN); | ||||||
|  |             scene_manager_next_scene(picopass->scene_manager, PicopassSceneWriteKey); | ||||||
|  |             consumed = true; | ||||||
|  |         } else if(event.event == SubmenuIndexWriteiCL) { | ||||||
|  |             scene_manager_set_scene_state( | ||||||
|  |                 picopass->scene_manager, PicopassSceneKeyMenu, SubmenuIndexWriteiCE); | ||||||
|  |             memcpy(picopass->dev->dev_data.pacs.key, picopass_xicl_key, PICOPASS_BLOCK_LEN); | ||||||
|  |             scene_manager_next_scene(picopass->scene_manager, PicopassSceneWriteKey); | ||||||
|  |             consumed = true; | ||||||
|  |         } else if(event.event == SubmenuIndexWriteiCS) { | ||||||
|  |             scene_manager_set_scene_state( | ||||||
|  |                 picopass->scene_manager, PicopassSceneKeyMenu, SubmenuIndexWriteiCE); | ||||||
|  |             memcpy(picopass->dev->dev_data.pacs.key, picopass_xics_key, PICOPASS_BLOCK_LEN); | ||||||
|  |             scene_manager_next_scene(picopass->scene_manager, PicopassSceneWriteKey); | ||||||
|  |             consumed = true; | ||||||
|  |         } | ||||||
|  |     } else if(event.type == SceneManagerEventTypeBack) { | ||||||
|  |         consumed = scene_manager_search_and_switch_to_previous_scene( | ||||||
|  |             picopass->scene_manager, PicopassSceneStart); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return consumed; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void picopass_scene_key_menu_on_exit(void* context) { | ||||||
|  |     Picopass* picopass = context; | ||||||
|  | 
 | ||||||
|  |     submenu_reset(picopass->submenu); | ||||||
|  | } | ||||||
| @ -1,7 +1,7 @@ | |||||||
| #include "../picopass_i.h" | #include "../picopass_i.h" | ||||||
| #include <dolphin/dolphin.h> | #include <dolphin/dolphin.h> | ||||||
| 
 | 
 | ||||||
| const uint8_t picopass_factory_key_check[] = {0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87}; | extern const uint8_t picopass_factory_debit_key[]; | ||||||
| 
 | 
 | ||||||
| void picopass_read_card_worker_callback(PicopassWorkerEvent event, void* context) { | void picopass_read_card_worker_callback(PicopassWorkerEvent event, void* context) { | ||||||
|     UNUSED(event); |     UNUSED(event); | ||||||
| @ -38,7 +38,7 @@ bool picopass_scene_read_card_on_event(void* context, SceneManagerEvent event) { | |||||||
|         if(event.event == PicopassCustomEventWorkerExit) { |         if(event.event == PicopassCustomEventWorkerExit) { | ||||||
|             if(memcmp( |             if(memcmp( | ||||||
|                    picopass->dev->dev_data.pacs.key, |                    picopass->dev->dev_data.pacs.key, | ||||||
|                    picopass_factory_key_check, |                    picopass_factory_debit_key, | ||||||
|                    PICOPASS_BLOCK_LEN) == 0) { |                    PICOPASS_BLOCK_LEN) == 0) { | ||||||
|                 scene_manager_next_scene(picopass->scene_manager, PicopassSceneReadFactorySuccess); |                 scene_manager_next_scene(picopass->scene_manager, PicopassSceneReadFactorySuccess); | ||||||
|             } else { |             } else { | ||||||
|  | |||||||
| @ -1,6 +1,8 @@ | |||||||
| #include "../picopass_i.h" | #include "../picopass_i.h" | ||||||
| #include <dolphin/dolphin.h> | #include <dolphin/dolphin.h> | ||||||
| 
 | 
 | ||||||
|  | extern const uint8_t picopass_iclass_key[]; | ||||||
|  | 
 | ||||||
| void picopass_scene_read_factory_success_widget_callback( | void picopass_scene_read_factory_success_widget_callback( | ||||||
|     GuiButtonType result, |     GuiButtonType result, | ||||||
|     InputType type, |     InputType type, | ||||||
| @ -63,6 +65,7 @@ bool picopass_scene_read_factory_success_on_event(void* context, SceneManagerEve | |||||||
|         if(event.event == GuiButtonTypeLeft) { |         if(event.event == GuiButtonTypeLeft) { | ||||||
|             consumed = scene_manager_previous_scene(picopass->scene_manager); |             consumed = scene_manager_previous_scene(picopass->scene_manager); | ||||||
|         } else if(event.event == GuiButtonTypeCenter) { |         } else if(event.event == GuiButtonTypeCenter) { | ||||||
|  |             memcpy(picopass->dev->dev_data.pacs.key, picopass_iclass_key, PICOPASS_BLOCK_LEN); | ||||||
|             scene_manager_next_scene(picopass->scene_manager, PicopassSceneWriteKey); |             scene_manager_next_scene(picopass->scene_manager, PicopassSceneWriteKey); | ||||||
|             consumed = true; |             consumed = true; | ||||||
|         } |         } | ||||||
|  | |||||||
| @ -20,7 +20,7 @@ void picopass_scene_write_key_on_enter(void* context) { | |||||||
|     view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewPopup); |     view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewPopup); | ||||||
|     picopass_worker_start( |     picopass_worker_start( | ||||||
|         picopass->worker, |         picopass->worker, | ||||||
|         PicopassWorkerStateWriteStandardKey, |         PicopassWorkerStateWriteKey, | ||||||
|         &picopass->dev->dev_data, |         &picopass->dev->dev_data, | ||||||
|         picopass_write_key_worker_callback, |         picopass_write_key_worker_callback, | ||||||
|         picopass); |         picopass); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Eric Betts
						Eric Betts