Picopass read bug fixes: (#2201)
* fix checking user elite keys * include calculated Kd when saving cards Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
		
							parent
							
								
									d7735a1efb
								
							
						
					
					
						commit
						90573fbeed
					
				| @ -18,6 +18,9 @@ | ||||
| 
 | ||||
| #define PICOPASS_CSN_BLOCK_INDEX 0 | ||||
| #define PICOPASS_CONFIG_BLOCK_INDEX 1 | ||||
| #define PICOPASS_EPURSE_BLOCK_INDEX 2 | ||||
| #define PICOPASS_KD_BLOCK_INDEX 3 | ||||
| #define PICOPASS_KC_BLOCK_INDEX 4 | ||||
| #define PICOPASS_AIA_BLOCK_INDEX 5 | ||||
| 
 | ||||
| #define PICOPASS_APP_FOLDER ANY_PATH("picopass") | ||||
|  | ||||
| @ -175,13 +175,12 @@ ReturnCode picopass_read_preauth(PicopassBlock* AA1) { | ||||
|     return ERR_NONE; | ||||
| } | ||||
| 
 | ||||
| ReturnCode picopass_auth(PicopassBlock* AA1, PicopassPacs* pacs) { | ||||
| static ReturnCode picopass_auth_standard(uint8_t* csn, uint8_t* div_key) { | ||||
|     rfalPicoPassReadCheckRes rcRes; | ||||
|     rfalPicoPassCheckRes chkRes; | ||||
| 
 | ||||
|     ReturnCode err; | ||||
| 
 | ||||
|     uint8_t div_key[8] = {0}; | ||||
|     uint8_t mac[4] = {0}; | ||||
|     uint8_t ccnr[12] = {0}; | ||||
| 
 | ||||
| @ -192,26 +191,34 @@ ReturnCode picopass_auth(PicopassBlock* AA1, PicopassPacs* pacs) { | ||||
|     } | ||||
|     memcpy(ccnr, rcRes.CCNR, sizeof(rcRes.CCNR)); // last 4 bytes left 0
 | ||||
| 
 | ||||
|     loclass_diversifyKey(AA1[PICOPASS_CSN_BLOCK_INDEX].data, picopass_iclass_key, div_key); | ||||
|     loclass_diversifyKey(csn, picopass_iclass_key, div_key); | ||||
|     loclass_opt_doReaderMAC(ccnr, div_key, mac); | ||||
| 
 | ||||
|     err = rfalPicoPassPollerCheck(mac, &chkRes); | ||||
|     if(err == ERR_NONE) { | ||||
|         return ERR_NONE; | ||||
|     } | ||||
|     FURI_LOG_E(TAG, "rfalPicoPassPollerCheck error %d", err); | ||||
|     return rfalPicoPassPollerCheck(mac, &chkRes); | ||||
| } | ||||
| 
 | ||||
|     FURI_LOG_E(TAG, "Starting dictionary attack"); | ||||
| static ReturnCode picopass_auth_dict( | ||||
|     uint8_t* csn, | ||||
|     PicopassPacs* pacs, | ||||
|     uint8_t* div_key, | ||||
|     IclassEliteDictType dict_type) { | ||||
|     rfalPicoPassReadCheckRes rcRes; | ||||
|     rfalPicoPassCheckRes chkRes; | ||||
| 
 | ||||
|     ReturnCode err = ERR_PARAM; | ||||
| 
 | ||||
|     uint8_t mac[4] = {0}; | ||||
|     uint8_t ccnr[12] = {0}; | ||||
| 
 | ||||
|     size_t index = 0; | ||||
|     uint8_t key[PICOPASS_BLOCK_LEN] = {0}; | ||||
| 
 | ||||
|     if(!iclass_elite_dict_check_presence(IclassEliteDictTypeFlipper)) { | ||||
|     if(!iclass_elite_dict_check_presence(dict_type)) { | ||||
|         FURI_LOG_E(TAG, "Dictionary not found"); | ||||
|         return ERR_PARAM; | ||||
|     } | ||||
| 
 | ||||
|     IclassEliteDict* dict = iclass_elite_dict_alloc(IclassEliteDictTypeFlipper); | ||||
|     IclassEliteDict* dict = iclass_elite_dict_alloc(dict_type); | ||||
|     if(!dict) { | ||||
|         FURI_LOG_E(TAG, "Dictionary not allocated"); | ||||
|         return ERR_PARAM; | ||||
| @ -235,11 +242,11 @@ ReturnCode picopass_auth(PicopassBlock* AA1, PicopassPacs* pacs) { | ||||
|         err = rfalPicoPassPollerReadCheck(&rcRes); | ||||
|         if(err != ERR_NONE) { | ||||
|             FURI_LOG_E(TAG, "rfalPicoPassPollerReadCheck error %d", err); | ||||
|             return err; | ||||
|             break; | ||||
|         } | ||||
|         memcpy(ccnr, rcRes.CCNR, sizeof(rcRes.CCNR)); // last 4 bytes left 0
 | ||||
| 
 | ||||
|         loclass_iclass_calc_div_key(AA1[PICOPASS_CSN_BLOCK_INDEX].data, key, div_key, true); | ||||
|         loclass_iclass_calc_div_key(csn, key, div_key, true); | ||||
|         loclass_opt_doReaderMAC(ccnr, div_key, mac); | ||||
| 
 | ||||
|         err = rfalPicoPassPollerCheck(mac, &chkRes); | ||||
| @ -254,6 +261,39 @@ ReturnCode picopass_auth(PicopassBlock* AA1, PicopassPacs* pacs) { | ||||
|     return err; | ||||
| } | ||||
| 
 | ||||
| ReturnCode picopass_auth(PicopassBlock* AA1, PicopassPacs* pacs) { | ||||
|     ReturnCode err; | ||||
| 
 | ||||
|     FURI_LOG_E(TAG, "Trying standard legacy key"); | ||||
|     err = picopass_auth_standard( | ||||
|         AA1[PICOPASS_CSN_BLOCK_INDEX].data, AA1[PICOPASS_KD_BLOCK_INDEX].data); | ||||
|     if(err == ERR_NONE) { | ||||
|         return ERR_NONE; | ||||
|     } | ||||
| 
 | ||||
|     FURI_LOG_E(TAG, "Starting user dictionary attack"); | ||||
|     err = picopass_auth_dict( | ||||
|         AA1[PICOPASS_CSN_BLOCK_INDEX].data, | ||||
|         pacs, | ||||
|         AA1[PICOPASS_KD_BLOCK_INDEX].data, | ||||
|         IclassEliteDictTypeUser); | ||||
|     if(err == ERR_NONE) { | ||||
|         return ERR_NONE; | ||||
|     } | ||||
| 
 | ||||
|     FURI_LOG_E(TAG, "Starting in-built dictionary attack"); | ||||
|     err = picopass_auth_dict( | ||||
|         AA1[PICOPASS_CSN_BLOCK_INDEX].data, | ||||
|         pacs, | ||||
|         AA1[PICOPASS_KD_BLOCK_INDEX].data, | ||||
|         IclassEliteDictTypeFlipper); | ||||
|     if(err == ERR_NONE) { | ||||
|         return ERR_NONE; | ||||
|     } | ||||
| 
 | ||||
|     return err; | ||||
| } | ||||
| 
 | ||||
| ReturnCode picopass_read_card(PicopassBlock* AA1) { | ||||
|     ReturnCode err; | ||||
| 
 | ||||
| @ -262,6 +302,11 @@ ReturnCode picopass_read_card(PicopassBlock* AA1) { | ||||
|                            PICOPASS_MAX_APP_LIMIT; | ||||
| 
 | ||||
|     for(size_t i = 2; i < app_limit; i++) { | ||||
|         if(i == PICOPASS_KD_BLOCK_INDEX) { | ||||
|             // Skip over Kd block which is populated earlier (READ of Kd returns all FF's)
 | ||||
|             continue; | ||||
|         } | ||||
| 
 | ||||
|         rfalPicoPassReadBlockRes block; | ||||
|         err = rfalPicoPassPollerReadBlock(i, &block); | ||||
|         if(err != ERR_NONE) { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Tiernan
						Tiernan