Picopass standard KDF dictionary (#2478)
* Split iclass dictionaries based on KDF * Allow cancelling during key test Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
		| @@ -5,6 +5,7 @@ | |||||||
|  |  | ||||||
| #define ICLASS_ELITE_DICT_FLIPPER_NAME APP_DATA_PATH("assets/iclass_elite_dict.txt") | #define ICLASS_ELITE_DICT_FLIPPER_NAME APP_DATA_PATH("assets/iclass_elite_dict.txt") | ||||||
| #define ICLASS_ELITE_DICT_USER_NAME APP_DATA_PATH("assets/iclass_elite_dict_user.txt") | #define ICLASS_ELITE_DICT_USER_NAME APP_DATA_PATH("assets/iclass_elite_dict_user.txt") | ||||||
|  | #define ICLASS_STANDARD_DICT_FLIPPER_NAME APP_DATA_PATH("assets/iclass_standard_dict.txt") | ||||||
|  |  | ||||||
| #define TAG "IclassEliteDict" | #define TAG "IclassEliteDict" | ||||||
|  |  | ||||||
| @@ -25,6 +26,9 @@ bool iclass_elite_dict_check_presence(IclassEliteDictType dict_type) { | |||||||
|             (storage_common_stat(storage, ICLASS_ELITE_DICT_FLIPPER_NAME, NULL) == FSE_OK); |             (storage_common_stat(storage, ICLASS_ELITE_DICT_FLIPPER_NAME, NULL) == FSE_OK); | ||||||
|     } else if(dict_type == IclassEliteDictTypeUser) { |     } else if(dict_type == IclassEliteDictTypeUser) { | ||||||
|         dict_present = (storage_common_stat(storage, ICLASS_ELITE_DICT_USER_NAME, NULL) == FSE_OK); |         dict_present = (storage_common_stat(storage, ICLASS_ELITE_DICT_USER_NAME, NULL) == FSE_OK); | ||||||
|  |     } else if(dict_type == IclassStandardDictTypeFlipper) { | ||||||
|  |         dict_present = | ||||||
|  |             (storage_common_stat(storage, ICLASS_STANDARD_DICT_FLIPPER_NAME, NULL) == FSE_OK); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     furi_record_close(RECORD_STORAGE); |     furi_record_close(RECORD_STORAGE); | ||||||
| @@ -52,6 +56,15 @@ IclassEliteDict* iclass_elite_dict_alloc(IclassEliteDictType dict_type) { | |||||||
|                 buffered_file_stream_close(dict->stream); |                 buffered_file_stream_close(dict->stream); | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|  |         } else if(dict_type == IclassStandardDictTypeFlipper) { | ||||||
|  |             if(!buffered_file_stream_open( | ||||||
|  |                    dict->stream, | ||||||
|  |                    ICLASS_STANDARD_DICT_FLIPPER_NAME, | ||||||
|  |                    FSAM_READ, | ||||||
|  |                    FSOM_OPEN_EXISTING)) { | ||||||
|  |                 buffered_file_stream_close(dict->stream); | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // Read total amount of keys |         // Read total amount of keys | ||||||
| @@ -148,4 +161,4 @@ bool iclass_elite_dict_add_key(IclassEliteDict* dict, uint8_t* key) { | |||||||
|  |  | ||||||
|     furi_string_free(key_str); |     furi_string_free(key_str); | ||||||
|     return key_added; |     return key_added; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -9,6 +9,7 @@ | |||||||
| typedef enum { | typedef enum { | ||||||
|     IclassEliteDictTypeUser, |     IclassEliteDictTypeUser, | ||||||
|     IclassEliteDictTypeFlipper, |     IclassEliteDictTypeFlipper, | ||||||
|  |     IclassStandardDictTypeFlipper, | ||||||
| } IclassEliteDictType; | } IclassEliteDictType; | ||||||
|  |  | ||||||
| typedef struct IclassEliteDict IclassEliteDict; | typedef struct IclassEliteDict IclassEliteDict; | ||||||
| @@ -25,4 +26,4 @@ bool iclass_elite_dict_get_next_key(IclassEliteDict* dict, uint8_t* key); | |||||||
|  |  | ||||||
| bool iclass_elite_dict_rewind(IclassEliteDict* dict); | bool iclass_elite_dict_rewind(IclassEliteDict* dict); | ||||||
|  |  | ||||||
| bool iclass_elite_dict_add_key(IclassEliteDict* dict, uint8_t* key); | bool iclass_elite_dict_add_key(IclassEliteDict* dict, uint8_t* key); | ||||||
|   | |||||||
							
								
								
									
										46
									
								
								applications/external/picopass/picopass_worker.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										46
									
								
								applications/external/picopass/picopass_worker.c
									
									
									
									
										vendored
									
									
								
							| @@ -172,14 +172,18 @@ ReturnCode picopass_read_preauth(PicopassBlock* AA1) { | |||||||
|     return ERR_NONE; |     return ERR_NONE; | ||||||
| } | } | ||||||
|  |  | ||||||
| static ReturnCode picopass_auth_dict( | static ReturnCode | ||||||
|     uint8_t* csn, |     picopass_auth_dict(PicopassWorker* picopass_worker, IclassEliteDictType dict_type) { | ||||||
|     PicopassPacs* pacs, |  | ||||||
|     uint8_t* div_key, |  | ||||||
|     IclassEliteDictType dict_type, |  | ||||||
|     bool elite) { |  | ||||||
|     rfalPicoPassReadCheckRes rcRes; |     rfalPicoPassReadCheckRes rcRes; | ||||||
|     rfalPicoPassCheckRes chkRes; |     rfalPicoPassCheckRes chkRes; | ||||||
|  |     bool elite = (dict_type != IclassStandardDictTypeFlipper); | ||||||
|  |  | ||||||
|  |     PicopassDeviceData* dev_data = picopass_worker->dev_data; | ||||||
|  |     PicopassBlock* AA1 = dev_data->AA1; | ||||||
|  |     PicopassPacs* pacs = &dev_data->pacs; | ||||||
|  |  | ||||||
|  |     uint8_t* csn = AA1[PICOPASS_CSN_BLOCK_INDEX].data; | ||||||
|  |     uint8_t* div_key = AA1[PICOPASS_KD_BLOCK_INDEX].data; | ||||||
|  |  | ||||||
|     ReturnCode err = ERR_PARAM; |     ReturnCode err = ERR_PARAM; | ||||||
|  |  | ||||||
| @@ -204,7 +208,8 @@ static ReturnCode picopass_auth_dict( | |||||||
|     while(iclass_elite_dict_get_next_key(dict, key)) { |     while(iclass_elite_dict_get_next_key(dict, key)) { | ||||||
|         FURI_LOG_D( |         FURI_LOG_D( | ||||||
|             TAG, |             TAG, | ||||||
|             "Try to auth with key %zu %02x%02x%02x%02x%02x%02x%02x%02x", |             "Try to %s auth with key %zu %02x%02x%02x%02x%02x%02x%02x%02x", | ||||||
|  |             elite ? "elite" : "standard", | ||||||
|             index++, |             index++, | ||||||
|             key[0], |             key[0], | ||||||
|             key[1], |             key[1], | ||||||
| @@ -230,6 +235,8 @@ static ReturnCode picopass_auth_dict( | |||||||
|             memcpy(pacs->key, key, PICOPASS_BLOCK_LEN); |             memcpy(pacs->key, key, PICOPASS_BLOCK_LEN); | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         if(picopass_worker->state != PicopassWorkerStateDetect) break; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     iclass_elite_dict_free(dict); |     iclass_elite_dict_free(dict); | ||||||
| @@ -237,38 +244,23 @@ static ReturnCode picopass_auth_dict( | |||||||
|     return err; |     return err; | ||||||
| } | } | ||||||
|  |  | ||||||
| ReturnCode picopass_auth(PicopassBlock* AA1, PicopassPacs* pacs) { | ReturnCode picopass_auth(PicopassWorker* picopass_worker) { | ||||||
|     ReturnCode err; |     ReturnCode err; | ||||||
|  |  | ||||||
|     FURI_LOG_I(TAG, "Starting system dictionary attack [Standard KDF]"); |     FURI_LOG_I(TAG, "Starting system dictionary attack [Standard KDF]"); | ||||||
|     err = picopass_auth_dict( |     err = picopass_auth_dict(picopass_worker, IclassStandardDictTypeFlipper); | ||||||
|         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; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     FURI_LOG_I(TAG, "Starting user dictionary attack [Elite KDF]"); |     FURI_LOG_I(TAG, "Starting user dictionary attack [Elite KDF]"); | ||||||
|     err = picopass_auth_dict( |     err = picopass_auth_dict(picopass_worker, IclassEliteDictTypeUser); | ||||||
|         AA1[PICOPASS_CSN_BLOCK_INDEX].data, |  | ||||||
|         pacs, |  | ||||||
|         AA1[PICOPASS_KD_BLOCK_INDEX].data, |  | ||||||
|         IclassEliteDictTypeUser, |  | ||||||
|         true); |  | ||||||
|     if(err == ERR_NONE) { |     if(err == ERR_NONE) { | ||||||
|         return ERR_NONE; |         return ERR_NONE; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     FURI_LOG_I(TAG, "Starting system dictionary attack [Elite KDF]"); |     FURI_LOG_I(TAG, "Starting system dictionary attack [Elite KDF]"); | ||||||
|     err = picopass_auth_dict( |     err = picopass_auth_dict(picopass_worker, IclassEliteDictTypeFlipper); | ||||||
|         AA1[PICOPASS_CSN_BLOCK_INDEX].data, |  | ||||||
|         pacs, |  | ||||||
|         AA1[PICOPASS_KD_BLOCK_INDEX].data, |  | ||||||
|         IclassEliteDictTypeFlipper, |  | ||||||
|         true); |  | ||||||
|     if(err == ERR_NONE) { |     if(err == ERR_NONE) { | ||||||
|         return ERR_NONE; |         return ERR_NONE; | ||||||
|     } |     } | ||||||
| @@ -520,7 +512,7 @@ void picopass_worker_detect(PicopassWorker* picopass_worker) { | |||||||
|             } |             } | ||||||
|  |  | ||||||
|             if(nextState == PicopassWorkerEventSuccess) { |             if(nextState == PicopassWorkerEventSuccess) { | ||||||
|                 err = picopass_auth(AA1, pacs); |                 err = picopass_auth(picopass_worker); | ||||||
|                 if(err != ERR_NONE) { |                 if(err != ERR_NONE) { | ||||||
|                     FURI_LOG_E(TAG, "picopass_try_auth error %d", err); |                     FURI_LOG_E(TAG, "picopass_try_auth error %d", err); | ||||||
|                     nextState = PicopassWorkerEventFail; |                     nextState = PicopassWorkerEventFail; | ||||||
|   | |||||||
| @@ -1,16 +1,10 @@ | |||||||
|  |  | ||||||
| ## From https://github.com/RfidResearchGroup/proxmark3/blob/master/client/dictionaries/iclass_default_keys.dic | ## From https://github.com/RfidResearchGroup/proxmark3/blob/master/client/dictionaries/iclass_default_keys.dic | ||||||
|  |  | ||||||
| # AA1 |  | ||||||
| AEA684A6DAB23278 |  | ||||||
| # key1/Kc from PicoPass 2k documentation | # key1/Kc from PicoPass 2k documentation | ||||||
| 7665544332211000 | 7665544332211000 | ||||||
| # SAGEM | # SAGEM | ||||||
| 0123456789ABCDEF | 0123456789ABCDEF | ||||||
| # from loclass demo file. |  | ||||||
| 5b7c62c491c11b39 |  | ||||||
| # Kd from PicoPass 2k documentation |  | ||||||
| F0E1D2C3B4A59687 |  | ||||||
| # PicoPass Default Exchange Key | # PicoPass Default Exchange Key | ||||||
| 5CBCF1DA45D5FB4F | 5CBCF1DA45D5FB4F | ||||||
| # From HID multiclassSE reader | # From HID multiclassSE reader | ||||||
| @@ -19,12 +13,6 @@ F0E1D2C3B4A59687 | |||||||
| 6EFD46EFCBB3C875 | 6EFD46EFCBB3C875 | ||||||
| E033CA419AEE43F9 | E033CA419AEE43F9 | ||||||
|  |  | ||||||
| # iCopy-x DRM keys |  | ||||||
| # iCL tags |  | ||||||
| 2020666666668888 |  | ||||||
| # iCS tags reversed from the SOs |  | ||||||
| 6666202066668888 |  | ||||||
|  |  | ||||||
| # default picopass KD / Page 0 / Book 1 | # default picopass KD / Page 0 / Book 1 | ||||||
| FDCB5A52EA8F3090 | FDCB5A52EA8F3090 | ||||||
| 237FF9079863DF44 | 237FF9079863DF44 | ||||||
|   | |||||||
| @@ -0,0 +1,47 @@ | |||||||
|  |  | ||||||
|  | ## From https://github.com/RfidResearchGroup/proxmark3/blob/master/client/dictionaries/iclass_default_keys.dic | ||||||
|  |  | ||||||
|  | # AA1 | ||||||
|  | AEA684A6DAB23278 | ||||||
|  | # key1/Kc from PicoPass 2k documentation | ||||||
|  | 7665544332211000 | ||||||
|  | # SAGEM | ||||||
|  | 0123456789ABCDEF | ||||||
|  | # from loclass demo file. | ||||||
|  | 5b7c62c491c11b39 | ||||||
|  | # Kd from PicoPass 2k documentation | ||||||
|  | F0E1D2C3B4A59687 | ||||||
|  | # PicoPass Default Exchange Key | ||||||
|  | 5CBCF1DA45D5FB4F | ||||||
|  | # From HID multiclassSE reader | ||||||
|  | 31ad7ebd2f282168 | ||||||
|  | # From pastebin: https://pastebin.com/uHqpjiuU | ||||||
|  | 6EFD46EFCBB3C875 | ||||||
|  | E033CA419AEE43F9 | ||||||
|  |  | ||||||
|  | # iCopy-x DRM keys | ||||||
|  | # iCL tags | ||||||
|  | 2020666666668888 | ||||||
|  | # iCS tags reversed from the SOs | ||||||
|  | 6666202066668888 | ||||||
|  |  | ||||||
|  | # default picopass KD / Page 0 / Book 1 | ||||||
|  | FDCB5A52EA8F3090 | ||||||
|  | 237FF9079863DF44 | ||||||
|  | 5ADC25FB27181D32 | ||||||
|  | 83B881F2936B2E49 | ||||||
|  | 43644E61EE866BA5 | ||||||
|  | 897034143D016080 | ||||||
|  | 82D17B44C0122963 | ||||||
|  | 4895CA7DE65E2025 | ||||||
|  | DADAD4C57BE271B7 | ||||||
|  | E41E9EDEF5719ABF | ||||||
|  | 293D275EC3AF9C7F | ||||||
|  | C3C169251B8A70FB | ||||||
|  | F41DAF58B20C8B91 | ||||||
|  | 28877A609EC0DD2B | ||||||
|  | 66584C91EE80D5E5 | ||||||
|  | C1B74D7478053AE2 | ||||||
|  |  | ||||||
|  | # default iCLASS RFIDeas | ||||||
|  | 6B65797374726B72 | ||||||
		Reference in New Issue
	
	Block a user