mirror of
				https://github.com/RfidResearchGroup/proxmark3.git
				synced 2025-11-01 00:46:39 +08:00 
			
		
		
		
	Merge pull request #2587 from douniwan5788/hts_resp_protocol
add: support for all Hitag S response protocol mode
This commit is contained in:
		
						commit
						9e8a5ab839
					
				
					 4 changed files with 217 additions and 221 deletions
				
			
		|  | @ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. | |||
| This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... | ||||
| 
 | ||||
| ## [unreleased][unreleased] | ||||
| - Added support for all Hitag S response protocol mode (@douniwan5788) | ||||
| - Fixed 'hf_young.c' - flags declaration was missing a semicolon (@jakkpotts) | ||||
| - Changed `hf mf sim` - add option to allow key b to be used even if readable (@doegox) | ||||
| - Changed `data num` - outputed binary strings are now properly zero padded (@iceman1001) | ||||
|  |  | |||
							
								
								
									
										340
									
								
								armsrc/hitagS.c
									
										
									
									
									
								
							
							
						
						
									
										340
									
								
								armsrc/hitagS.c
									
										
									
									
									
								
							|  | @ -65,6 +65,7 @@ typedef enum modulation { | |||
|     MC8K | ||||
| } MOD; | ||||
| 
 | ||||
| static uint8_t protocol_mode = HITAGS_UID_REQ_ADV1; | ||||
| static MOD m = AC2K;                                // used modulation
 | ||||
| static uint32_t reader_selected_uid; | ||||
| static int rotate_uid = 0; | ||||
|  | @ -383,18 +384,17 @@ static void hts_init_clock(void) { | |||
|     // Disable timer during configuration
 | ||||
|     hts_stop_clock(); | ||||
| 
 | ||||
|     // TC0: Capture mode, clock source = MCK/32 (TIMER_CLOCK3), no triggers
 | ||||
|     // TC0: Capture mode, default timer source = MCK/32 (TIMER_CLOCK3), no triggers
 | ||||
|     AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK; | ||||
| 
 | ||||
|     // TC1: Capture mode, clock source = MCK/32 (TIMER_CLOCK3), TIOA is external trigger,
 | ||||
|     // external trigger falling edge, set RA on falling edge of TIOA.
 | ||||
|     AT91C_BASE_TC1->TC_CMR = | ||||
|         AT91C_TC_CLKS_TIMER_DIV3_CLOCK |    // MCK/32 (TIMER_CLOCK3)
 | ||||
|         AT91C_TC_ETRGEDG_FALLING |          // external trigger on falling edge
 | ||||
|         AT91C_TC_ABETRG |                   // TIOA is used as an external trigger
 | ||||
|         AT91C_TC_LDRA_FALLING;              // load RA on on falling edge
 | ||||
|     // TC1: Capture mode, default timer source = MCK/32 (TIMER_CLOCK3), TIOA is external trigger,
 | ||||
|     AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK  // use MCK/32 (TIMER_CLOCK3)
 | ||||
|                              | AT91C_TC_ABETRG               // TIOA is used as an external trigger
 | ||||
|                              | AT91C_TC_ETRGEDG_FALLING      // external trigger on falling edge
 | ||||
|                              | AT91C_TC_LDRA_RISING          // load RA on on rising edge of TIOA
 | ||||
|                              | AT91C_TC_LDRB_FALLING;        // load RB on on falling edge of TIOA
 | ||||
| 
 | ||||
|     // TC2: Capture mode, clock source = MCK/32 (TIMER_CLOCK3), no triggers
 | ||||
|     // TC2: Capture mode, default timer source = MCK/32 (TIMER_CLOCK3), no triggers
 | ||||
|     AT91C_BASE_TC2->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK; | ||||
| 
 | ||||
|     // Enable and reset counters
 | ||||
|  | @ -429,24 +429,35 @@ static int check_select(const uint8_t *rx, uint32_t uid) { | |||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| static void hts_set_frame_modulation(void) { | ||||
|     switch (tag.mode) { | ||||
|         case HT_STANDARD: { | ||||
| static void hts_set_frame_modulation(uint8_t mode, bool ac_seq) { | ||||
|     switch (mode) { | ||||
|         case HITAGS_UID_REQ_STD: { | ||||
|             sof_bits = 1; | ||||
|             m = MC4K; | ||||
|             if (ac_seq) | ||||
|                 m = AC2K; | ||||
|             else | ||||
|                 m = MC4K; | ||||
|             break; | ||||
|         } | ||||
|         case HT_ADVANCED: { | ||||
|             sof_bits = 6; | ||||
|             m = MC4K; | ||||
|         case HITAGS_UID_REQ_ADV1: | ||||
|         case HITAGS_UID_REQ_ADV2: { | ||||
|             if (ac_seq) { | ||||
|                 sof_bits = 3; | ||||
|                 m = AC2K; | ||||
|             } else { | ||||
|                 sof_bits = 6; | ||||
|                 m = MC4K; | ||||
|             } | ||||
|             break; | ||||
|         } | ||||
|         case HT_FAST_ADVANCED: { | ||||
|             sof_bits = 6; | ||||
|             m = MC8K; | ||||
|             break; | ||||
|         } | ||||
|         default: { | ||||
|         case HITAGS_UID_REQ_FADV: { | ||||
|             if (ac_seq) { | ||||
|                 sof_bits = 3; | ||||
|                 m = AC4K; | ||||
|             } else { | ||||
|                 sof_bits = 6; | ||||
|                 m = MC8K; | ||||
|             } | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | @ -463,7 +474,7 @@ static void hts_handle_reader_command(uint8_t *rx, const size_t rxlen, | |||
|     // Reset the transmission frame length
 | ||||
|     *txlen = 0; | ||||
|     // Reset the frame modulation
 | ||||
|     hts_set_frame_modulation(); | ||||
|     hts_set_frame_modulation(protocol_mode, false); | ||||
| 
 | ||||
|     // Try to find out which command was send by selecting on length (in bits)
 | ||||
|     switch (rxlen) { | ||||
|  | @ -475,24 +486,15 @@ static void hts_handle_reader_command(uint8_t *rx, const size_t rxlen, | |||
| 
 | ||||
|             if (rx[0] == HITAGS_UID_REQ_STD) { | ||||
|                 DBG Dbprintf("HT_STANDARD"); | ||||
|                 tag.mode = HT_STANDARD; | ||||
|                 sof_bits = 1; | ||||
|                 m = AC2K; | ||||
|             } | ||||
| 
 | ||||
|             if (rx[0] == HITAGS_UID_REQ_ADV1 || rx[0] == HITAGS_UID_REQ_ADV2) { | ||||
|             } else if (rx[0] == HITAGS_UID_REQ_ADV1 || rx[0] == HITAGS_UID_REQ_ADV2) { | ||||
|                 DBG Dbprintf("HT_ADVANCED"); | ||||
|                 tag.mode = HT_ADVANCED; | ||||
|                 sof_bits = 3; | ||||
|                 m = AC2K; | ||||
|             } else if (rx[0] == HITAGS_UID_REQ_FADV) { | ||||
|                 DBG Dbprintf("HT_FAST_ADVANCED"); | ||||
|             } | ||||
| 
 | ||||
|             if (rx[0] == HITAGS_UID_REQ_FADV) { | ||||
|                 DBG Dbprintf("HT_FAST_ADVANCED"); | ||||
|                 tag.mode = HT_FAST_ADVANCED; | ||||
|                 sof_bits = 3; | ||||
|                 m = AC4K; | ||||
|             } | ||||
|             protocol_mode = rx[0]; | ||||
|             hts_set_frame_modulation(protocol_mode, true); | ||||
| 
 | ||||
|             //send uid as a response
 | ||||
|             *txlen = 32; | ||||
|             memcpy(tx, tag.data.pages[HITAGS_UID_PADR], HITAGS_PAGE_SIZE); | ||||
|  | @ -515,7 +517,7 @@ static void hts_handle_reader_command(uint8_t *rx, const size_t rxlen, | |||
| 
 | ||||
|                 tx[3] = 0xff; | ||||
| 
 | ||||
|                 if (tag.mode != HT_STANDARD) { | ||||
|                 if (protocol_mode != HITAGS_UID_REQ_STD) { | ||||
|                     //add crc8
 | ||||
|                     *txlen += 8; | ||||
|                     crc = CRC_PRESET; | ||||
|  | @ -549,7 +551,7 @@ static void hts_handle_reader_command(uint8_t *rx, const size_t rxlen, | |||
|             tx[2] = ht2_hitag2_byte(&state) ^ tag.data.s.pwdl0; | ||||
|             tx[3] = ht2_hitag2_byte(&state) ^ tag.data.s.pwdl1; | ||||
| 
 | ||||
|             if (tag.mode != HT_STANDARD) { | ||||
|             if (protocol_mode != HITAGS_UID_REQ_STD) { | ||||
|                 //add crc8
 | ||||
|                 *txlen += 8; | ||||
|                 crc = CRC_PRESET; | ||||
|  | @ -616,7 +618,7 @@ static void hts_handle_reader_command(uint8_t *rx, const size_t rxlen, | |||
|                     tx[3] = 0xFF; | ||||
|                 } | ||||
| 
 | ||||
|                 if (tag.mode != HT_STANDARD) { | ||||
|                 if (protocol_mode != HITAGS_UID_REQ_STD) { | ||||
|                     //add crc8
 | ||||
|                     *txlen += 8; | ||||
|                     crc = CRC_PRESET; | ||||
|  | @ -638,7 +640,7 @@ static void hts_handle_reader_command(uint8_t *rx, const size_t rxlen, | |||
|                 //send page,...,page+3 data
 | ||||
|                 memcpy(tx, tag.data.pages[page], *txlen / 8); | ||||
| 
 | ||||
|                 if (tag.mode != HT_STANDARD) { | ||||
|                 if (protocol_mode != HITAGS_UID_REQ_STD) { | ||||
|                     //add crc8
 | ||||
|                     crc = CRC_PRESET; | ||||
|                     for (int i = 0; i < *txlen / 8; i++) { | ||||
|  | @ -751,40 +753,7 @@ void hts_simulate(bool tag_mem_supplied, const uint8_t *data, bool ledcontrol) { | |||
|     // Disable modulation at default, which means release resistance
 | ||||
|     LOW(GPIO_SSC_DOUT); | ||||
| 
 | ||||
|     // Enable Peripheral Clock for
 | ||||
|     //   Timer Counter 0, used to measure exact timing before answering
 | ||||
|     //   Timer Counter 1, used to capture edges of the tag frames
 | ||||
|     //   Timer Counter 2, used to log trace time
 | ||||
|     AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1) | (1 << AT91C_ID_TC2); | ||||
| 
 | ||||
|     AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; | ||||
| 
 | ||||
|     // Disable timer during configuration
 | ||||
|     hts_stop_clock(); | ||||
| 
 | ||||
|     // TC0: Capture mode, default timer source = MCK/32 (TIMER_CLOCK3), no triggers
 | ||||
|     AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK; | ||||
| 
 | ||||
|     // TC1: Capture mode, default timer source = MCK/32 (TIMER_CLOCK3), TIOA is external trigger,
 | ||||
|     // external trigger rising edge, load RA on rising edge of TIOA.
 | ||||
|     AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK | ||||
|                              | AT91C_TC_ETRGEDG_RISING | AT91C_TC_ABETRG | AT91C_TC_LDRA_RISING; | ||||
|     // TC2: Capture mode, default timer source = MCK/32 (TIMER_CLOCK3), no triggers
 | ||||
|     AT91C_BASE_TC2->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK; | ||||
| 
 | ||||
|     // Enable and reset counter
 | ||||
|     AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; | ||||
|     AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; | ||||
|     AT91C_BASE_TC2->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; | ||||
| 
 | ||||
|     // Assert a sync signal. This sets all timers to 0 on next active clock edge
 | ||||
|     AT91C_BASE_TCB->TCB_BCR = 1; | ||||
| 
 | ||||
|     // synchronized startup procedure
 | ||||
|     while (AT91C_BASE_TC0->TC_CV != 0); // wait until TC0 returned to zero
 | ||||
| 
 | ||||
|     // reset timestamp
 | ||||
|     timestamp_high = 0; | ||||
|     hts_init_clock(); | ||||
| 
 | ||||
|     if (ledcontrol) LED_D_ON(); | ||||
| 
 | ||||
|  | @ -890,21 +859,29 @@ static void hts_receive_frame(uint8_t *rx, size_t sizeofrx, size_t *rxlen, uint3 | |||
|     bool bSkip = true; | ||||
|     uint32_t errorCount = 0; | ||||
|     bool bStarted = false; | ||||
|     uint16_t next_edge_event = AT91C_TC_LDRBS; | ||||
|     int double_speed = (m == AC4K || m == MC8K) ? 2 : 1; | ||||
| 
 | ||||
|     uint32_t ra_i = 0, h2 = 0, h3 = 0, h4 = 0; | ||||
|     uint32_t rb_i = 0, h2 = 0, h3 = 0, h4 = 0; | ||||
|     uint8_t edges[160] = {0}; | ||||
| 
 | ||||
|     // Dbprintf("TC0_CV:%i TC1_CV:%i TC1_RA:%i", AT91C_BASE_TC0->TC_CV, AT91C_BASE_TC1->TC_CV ,AT91C_BASE_TC1->TC_RA);
 | ||||
|     // Dbprintf("TC0_CV:%i TC1_CV:%i TC1_RB:%i TIMESTAMP:%u", AT91C_BASE_TC0->TC_CV, AT91C_BASE_TC1->TC_CV,
 | ||||
|     //          AT91C_BASE_TC1->TC_RB, TIMESTAMP);
 | ||||
| 
 | ||||
|     // Receive tag frame, watch for at most T0*HITAG_T_PROG_MAX periods
 | ||||
|     while (AT91C_BASE_TC0->TC_CV < (T0 * HITAG_T_PROG_MAX)) { | ||||
| 
 | ||||
|         // Check if falling edge in tag modulation is detected
 | ||||
|         if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) { | ||||
|         // Check if edge in tag modulation is detected
 | ||||
|         if (AT91C_BASE_TC1->TC_SR & next_edge_event) { | ||||
| 
 | ||||
|             next_edge_event = next_edge_event ^ (AT91C_TC_LDRAS | AT91C_TC_LDRBS); | ||||
| 
 | ||||
|             // only use AT91C_TC_LDRBS falling edge for now
 | ||||
|             if (next_edge_event == AT91C_TC_LDRBS) continue; | ||||
| 
 | ||||
|             // Retrieve the new timing values
 | ||||
|             uint32_t ra = AT91C_BASE_TC1->TC_RA / T0; | ||||
|             edges[ra_i++] = ra; | ||||
|             uint32_t rb = AT91C_BASE_TC1->TC_RB / T0; | ||||
|             edges[rb_i++] = rb; | ||||
|             // Reset timer every frame, we have to capture the last edge for timing
 | ||||
|             AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; | ||||
| 
 | ||||
|  | @ -916,7 +893,7 @@ static void hts_receive_frame(uint8_t *rx, size_t sizeofrx, size_t *rxlen, uint3 | |||
|             // Capture tag frame (manchester decoding using only falling edges)
 | ||||
|             if (bStarted == false) { | ||||
| 
 | ||||
|                 if (ra >= HITAG_T_WAIT_RESP) { | ||||
|                 if (rb >= HITAG_T_WAIT_RESP) { | ||||
|                     bStarted = true; | ||||
| 
 | ||||
|                     // We always receive a 'one' first, which has the falling edge after a half period |-_|
 | ||||
|  | @ -926,39 +903,69 @@ static void hts_receive_frame(uint8_t *rx, size_t sizeofrx, size_t *rxlen, uint3 | |||
|                     errorCount++; | ||||
|                 } | ||||
| 
 | ||||
|             } else if (ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) { | ||||
| 
 | ||||
|                 // Manchester coding example |-_|_-|-_| (101)
 | ||||
|                 rx[(*rxlen) / 8] |= 0 << (7 - ((*rxlen) % 8)); | ||||
|                 (*rxlen)++; | ||||
| 
 | ||||
|                 rx[(*rxlen) / 8] |= 1 << (7 - ((*rxlen) % 8)); | ||||
|                 (*rxlen)++; | ||||
|                 h4++; | ||||
|             } else if (ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) { | ||||
| 
 | ||||
|                 // Manchester coding example |_-|...|_-|-_| (0...01)
 | ||||
|                 rx[(*rxlen) / 8] |= 0 << (7 - ((*rxlen) % 8)); | ||||
|                 (*rxlen)++; | ||||
| 
 | ||||
|                 // We have to skip this half period at start and add the 'one' the second time
 | ||||
|                 if (bSkip == false) { | ||||
|                     rx[(*rxlen) / 8] |= 1 << (7 - ((*rxlen) % 8)); | ||||
|                     (*rxlen)++; | ||||
|                 } | ||||
| 
 | ||||
|                 lastbit = !lastbit; | ||||
|                 bSkip = !bSkip; | ||||
|                 h3++; | ||||
|             } else if (ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) { | ||||
|                 // Manchester coding example |_-|_-| (00) or |-_|-_| (11)
 | ||||
|                 // bit is same as last bit
 | ||||
|                 rx[(*rxlen) / 8] |= lastbit << (7 - ((*rxlen) % 8)); | ||||
|                 (*rxlen)++; | ||||
|                 h2++; | ||||
|             } else { | ||||
|                 // Ignore weird value, is to small to mean anything
 | ||||
|                 errorCount++; | ||||
|                 // Anticollision Coding
 | ||||
|                 if (m == AC2K || m == AC4K) { | ||||
|                     if (rb >= HITAG_T_TAG_CAPTURE_FOUR_HALF / double_speed) { | ||||
|                         // Anticollision Coding example |--__|--__| (00)
 | ||||
|                         lastbit = 0; | ||||
|                         rx[(*rxlen) / 8] |= lastbit << (7 - ((*rxlen) % 8)); | ||||
|                         (*rxlen)++; | ||||
|                     } else if (rb >= HITAG_T_TAG_CAPTURE_THREE_HALF / double_speed) { | ||||
|                         // Anticollision Coding example |-_-_|--__| (10) or |--__|-_-_| (01)
 | ||||
|                         lastbit = !lastbit; | ||||
|                         rx[(*rxlen) / 8] |= lastbit << (7 - ((*rxlen) % 8)); | ||||
|                         (*rxlen)++; | ||||
| 
 | ||||
|                         bSkip = !!lastbit; | ||||
|                     } else if (rb >= HITAG_T_TAG_CAPTURE_TWO_HALF / double_speed) { | ||||
|                         // Anticollision Coding example |-_-_| (1)
 | ||||
|                         if (bSkip == false) { | ||||
|                             lastbit = 1; | ||||
|                             rx[(*rxlen) / 8] |= lastbit << (7 - ((*rxlen) % 8)); | ||||
|                             (*rxlen)++; | ||||
|                         } | ||||
| 
 | ||||
|                         bSkip = !bSkip; | ||||
|                     } else { | ||||
|                         // Ignore weird value, is to small to mean anything
 | ||||
|                         errorCount++; | ||||
|                     } | ||||
|                 } else { | ||||
|                     // Manchester coding
 | ||||
|                     if (rb >= HITAG_T_TAG_CAPTURE_FOUR_HALF / double_speed) { | ||||
|                         // Manchester coding example |-_|_-|-_| (101)
 | ||||
|                         rx[(*rxlen) / 8] |= 0 << (7 - ((*rxlen) % 8)); | ||||
|                         (*rxlen)++; | ||||
| 
 | ||||
|                         rx[(*rxlen) / 8] |= 1 << (7 - ((*rxlen) % 8)); | ||||
|                         (*rxlen)++; | ||||
|                         h4++; | ||||
|                     } else if (rb >= HITAG_T_TAG_CAPTURE_THREE_HALF / double_speed) { | ||||
|                         // Manchester coding example |_-|...|_-|-_| (0...01)
 | ||||
|                         rx[(*rxlen) / 8] |= 0 << (7 - ((*rxlen) % 8)); | ||||
|                         (*rxlen)++; | ||||
| 
 | ||||
|                         // We have to skip this half period at start and add the 'one' the second time
 | ||||
|                         if (bSkip == false) { | ||||
|                             rx[(*rxlen) / 8] |= 1 << (7 - ((*rxlen) % 8)); | ||||
|                             (*rxlen)++; | ||||
|                         } | ||||
| 
 | ||||
|                         lastbit = !lastbit; | ||||
|                         bSkip = !bSkip; | ||||
|                         h3++; | ||||
|                     } else if (rb >= HITAG_T_TAG_CAPTURE_TWO_HALF / double_speed) { | ||||
|                         // Manchester coding example |_-|_-| (00) or |-_|-_| (11)
 | ||||
|                         // bit is same as last bit
 | ||||
|                         rx[(*rxlen) / 8] |= lastbit << (7 - ((*rxlen) % 8)); | ||||
|                         (*rxlen)++; | ||||
|                         h2++; | ||||
|                     } else { | ||||
|                         // Ignore weird value, is to small to mean anything
 | ||||
|                         errorCount++; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|  | @ -979,10 +986,10 @@ static void hts_receive_frame(uint8_t *rx, size_t sizeofrx, size_t *rxlen, uint3 | |||
|     } | ||||
| 
 | ||||
|     DBG Dbprintf("RX0 %i:%02X.. err:%i resptime:%i h2:%i h3:%i h4:%i edges:", *rxlen, rx[0], errorCount, *resptime, h2, h3, h4); | ||||
|     DBG Dbhexdump(ra_i, edges, false); | ||||
|     DBG Dbhexdump(rb_i, edges, false); | ||||
| } | ||||
| 
 | ||||
| static int hts_send_receive(const uint8_t *tx, size_t txlen, uint8_t *rx, size_t sizeofrx, size_t *prxbits, int t_wait, bool ledcontrol, bool ac_seq) { | ||||
| static int hts_send_receive(const uint8_t *tx, size_t txlen, uint8_t *rx, size_t sizeofrx, size_t *rxlen, int t_wait, bool ledcontrol, bool ac_seq) { | ||||
|     uint32_t start_time; | ||||
| 
 | ||||
|     // Send and store the reader command
 | ||||
|  | @ -1010,73 +1017,41 @@ static int hts_send_receive(const uint8_t *tx, size_t txlen, uint8_t *rx, size_t | |||
|     // Enable and reset external trigger in timer for capturing future frames
 | ||||
|     AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; | ||||
| 
 | ||||
|     size_t rxlen = 0; | ||||
|     hts_receive_frame(rx, sizeofrx, &rxlen, &start_time, ledcontrol); | ||||
|     int k = 0; | ||||
|     hts_set_frame_modulation(protocol_mode, ac_seq); | ||||
| 
 | ||||
|     hts_receive_frame(rx, sizeofrx, rxlen, &start_time, ledcontrol); | ||||
| 
 | ||||
|     // Check if frame was captured and store it
 | ||||
|     if (rxlen > 0) { | ||||
|     if (*rxlen > 0) { | ||||
|         DBG { | ||||
|             uint8_t response_bit[sizeofrx * 8]; | ||||
| 
 | ||||
|         uint8_t response_bit[sizeofrx * 8]; | ||||
| 
 | ||||
|         for (size_t i = 0; i < rxlen; i++) { | ||||
|             response_bit[i] = (rx[i / 8] >> (7 - (i % 8))) & 1; | ||||
|         } | ||||
| 
 | ||||
|         DBG Dbprintf("htS: rxlen...... %zu", rxlen); | ||||
|         DBG Dbprintf("htS: sizeofrx... %zu", sizeofrx); | ||||
|         DBG DbpString("htS: response_bit:"); | ||||
|         DBG Dbhexdump(rxlen, response_bit, false); | ||||
| 
 | ||||
|         memset(rx, 0x00, sizeofrx); | ||||
| 
 | ||||
|         if (ac_seq) { | ||||
| 
 | ||||
|             // Tag Response is AC encoded
 | ||||
|             // We used UID Request Advanced,  meaning AC SEQ SOF is  111.
 | ||||
|             for (int i = 7; i < rxlen; i += 2) { | ||||
| 
 | ||||
|                 rx[k / 8] |= response_bit[i] << (7 - (k % 8)); | ||||
| 
 | ||||
|                 k++; | ||||
| 
 | ||||
|                 if (k > 8 * sizeofrx) { | ||||
|                     break; | ||||
|                 } | ||||
|             for (size_t i = 0; i < *rxlen; i++) { | ||||
|                 response_bit[i] = (rx[i / 8] >> (7 - (i % 8))) & 1; | ||||
|             } | ||||
| 
 | ||||
|             // TODO: It's very confusing to reinterpreter the MC to AC; we should implement a more straightforward approach.
 | ||||
|             // add the lost bit zero, when AC64 last bit is zero
 | ||||
|             if (k % 8 == 7) { | ||||
|                 k++; | ||||
|             } | ||||
| 
 | ||||
|             if (g_dbglevel >= DBG_EXTENDED) { | ||||
|                 DbpString("htS: ac sequence compress"); | ||||
|                 Dbhexdump(k / 8, rx, false); | ||||
|             } | ||||
| 
 | ||||
|         } else { | ||||
| 
 | ||||
|             if (g_dbglevel >= DBG_EXTENDED) { | ||||
|                 DbpString("htS: skipping 6 bit header"); | ||||
|             } | ||||
| 
 | ||||
|             // ignore first 6 bits: SOF (actually 1 or 6 depending on response protocol)
 | ||||
|             // or rather a header.
 | ||||
|             for (size_t i = 6; i < rxlen; i++) { | ||||
| 
 | ||||
|                 rx[k / 8] |= response_bit[i] << (7 - (k % 8)); | ||||
|                 k++; | ||||
| 
 | ||||
|                 if (k > 8 * sizeofrx) { | ||||
|                     break; | ||||
|                 } | ||||
|             Dbprintf("htS: rxlen...... %zu", *rxlen); | ||||
|             Dbprintf("htS: sizeofrx... %zu", sizeofrx); | ||||
|             DbpString("htS: response_bit:"); | ||||
|             Dbhexdump(*rxlen, response_bit, false); | ||||
|             Dbprintf("htS: skipping %d bit SOF", sof_bits); | ||||
|             if ((rx[0] >> (8 - sof_bits)) != ((1 << sof_bits) - 1)) { | ||||
|                 DbpString("htS: Warning, not all bits of SOF are 1"); | ||||
|             } | ||||
|         } | ||||
|         LogTraceBits(rx, k, start_time, TIMESTAMP, false); | ||||
| 
 | ||||
|         // remove first sof_bits bits SOF
 | ||||
|         for (size_t i = 0; i < (*rxlen + 8) / 8; i++) { | ||||
|             rx[i] <<= sof_bits; | ||||
|             if (i + 1 < (*rxlen + 8) / 8) { | ||||
|                 rx[i] |= (rx[i + 1] >> (8 - sof_bits)); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         *rxlen -= sof_bits; | ||||
| 
 | ||||
|         LogTraceBits(rx, *rxlen, start_time, TIMESTAMP, false); | ||||
|     } | ||||
|     *prxbits = k; | ||||
| 
 | ||||
|     return PM3_SUCCESS; | ||||
| } | ||||
|  | @ -1112,7 +1087,9 @@ static int hts_select_tag(const lf_hitag_data_t *packet, uint8_t *tx, size_t siz | |||
|     // UID request FAdvanced  11010
 | ||||
|     size_t txlen = 0; | ||||
|     size_t rxlen = 0; | ||||
|     uint8_t cmd = HITAGS_UID_REQ_ADV1; | ||||
| 
 | ||||
|     protocol_mode = packet->mode; | ||||
|     uint8_t cmd = protocol_mode; | ||||
|     txlen = concatbits(tx, txlen, &cmd, 0, 5); | ||||
|     hts_send_receive(tx, txlen, rx, sizeofrx, &rxlen, t_wait, ledcontrol, true); | ||||
| 
 | ||||
|  | @ -1135,7 +1112,7 @@ static int hts_select_tag(const lf_hitag_data_t *packet, uint8_t *tx, size_t siz | |||
| 
 | ||||
|     hts_send_receive(tx, txlen, rx, sizeofrx, &rxlen, HITAG_T_WAIT_SC, ledcontrol, false); | ||||
| 
 | ||||
|     if (rxlen != 40) { | ||||
|     if (rxlen != 32 + (protocol_mode == HITAGS_UID_REQ_STD ? 0 : 8)) { | ||||
|         DBG Dbprintf("Select UID failed! %i", rxlen); | ||||
|         return -3; | ||||
|     } | ||||
|  | @ -1234,7 +1211,7 @@ static int hts_select_tag(const lf_hitag_data_t *packet, uint8_t *tx, size_t siz | |||
| 
 | ||||
|         hts_send_receive(tx, txlen, rx, sizeofrx, &rxlen, HITAG_T_WAIT_SC, ledcontrol, false); | ||||
| 
 | ||||
|         if (rxlen != 40) { | ||||
|         if (rxlen != 32 + (protocol_mode == HITAGS_UID_REQ_STD ? 0 : 8)) { | ||||
|             DBG Dbprintf("Authenticate failed! " _RED_("%i"), rxlen); | ||||
|             return -8; | ||||
|         } | ||||
|  | @ -1310,7 +1287,7 @@ void hts_read(const lf_hitag_data_t *payload, bool ledcontrol) { | |||
| 
 | ||||
|         hts_send_receive(tx, txlen, rx, ARRAYLEN(rx), &rxlen, HITAG_T_WAIT_SC, ledcontrol, false); | ||||
| 
 | ||||
|         if (rxlen != 40) { | ||||
|         if (rxlen != 32 + (protocol_mode == HITAGS_UID_REQ_STD ? 0 : 8)) { | ||||
|             DBG Dbprintf("Read page failed!"); | ||||
|             card.pages_reason[page_index] = -4; | ||||
|             // status = PM3_ERFTRANS;
 | ||||
|  | @ -1505,7 +1482,8 @@ int hts_read_uid(uint32_t *uid, bool ledcontrol, bool send_answer) { | |||
|     // UID request standard   00110
 | ||||
|     // UID request Advanced   1100x
 | ||||
|     // UID request FAdvanced  11010
 | ||||
|     uint8_t cmd = HITAGS_UID_REQ_ADV1; | ||||
|     protocol_mode = HITAGS_UID_REQ_ADV1; | ||||
|     uint8_t cmd = protocol_mode; | ||||
| 
 | ||||
|     size_t rxlen = 0; | ||||
|     uint8_t rx[HITAG_FRAME_LEN] = { 0x00 }; | ||||
|  |  | |||
|  | @ -147,6 +147,13 @@ static int process_hitags_common_args(CLIParserContext *ctx, lf_hitag_data_t *co | |||
|         return PM3_EINVARG; | ||||
|     } | ||||
| 
 | ||||
|     uint8_t mode = arg_get_int_def(ctx, 5, 3); | ||||
| 
 | ||||
|     if (mode > 3) { | ||||
|         PrintAndLogEx(WARNING, "Wrong response protocol mode, expected 0, 1, 2 or 3, got %d", mode); | ||||
|         return PM3_EINVARG; | ||||
|     } | ||||
| 
 | ||||
|     // complete options
 | ||||
|     switch (key_len) { | ||||
|         case HITAG_PASSWORD_SIZE: | ||||
|  | @ -194,6 +201,21 @@ static int process_hitags_common_args(CLIParserContext *ctx, lf_hitag_data_t *co | |||
|         PrintAndLogEx(INFO, "Authenticating to " _YELLOW_("Hitag S") " in Crypto mode"); | ||||
|     } | ||||
| 
 | ||||
|     switch (mode) { | ||||
|         case 0: | ||||
|             packet->mode = HITAGS_UID_REQ_STD; | ||||
|             break; | ||||
|         case 1: | ||||
|             packet->mode = HITAGS_UID_REQ_ADV1; | ||||
|             break; | ||||
|         case 2: | ||||
|             packet->mode = HITAGS_UID_REQ_ADV2; | ||||
|             break; | ||||
|         default: | ||||
|             packet->mode = HITAGS_UID_REQ_FADV; | ||||
|             break; | ||||
|     } | ||||
| 
 | ||||
|     return PM3_SUCCESS; | ||||
| } | ||||
| 
 | ||||
|  | @ -254,8 +276,9 @@ static int CmdLFHitagSRead(const char *Cmd) { | |||
|         arg_str0(NULL, "nrar", "<hex>", "nonce / answer writer, 8 hex bytes"), | ||||
|         arg_lit0(NULL, "crypto", "crypto mode"), | ||||
|         arg_str0("k", "key", "<hex>", "pwd or key, 4 or 6 hex bytes"), | ||||
|         arg_int0("m", "mode", "<dec>", "response protocol mode. 0 (Standard 00110), 1 (Advanced 11000), 2 (Advanced 11001), 3 (Fast Advanced 11010) (def: 3)"), | ||||
|         arg_int0("p", "page", "<dec>", "page address to read from"), | ||||
|         arg_int0("c", "count", "<dec>", "how many pages to read. '0' reads all pages up to the end page (default: 1)"), | ||||
|         arg_int0("c", "count", "<dec>", "how many pages to read. '0' reads all pages up to the end page (def: 1)"), | ||||
|         arg_param_end | ||||
|     }; | ||||
|     CLIExecWithReturn(ctx, Cmd, argtable, true); | ||||
|  | @ -264,14 +287,14 @@ static int CmdLFHitagSRead(const char *Cmd) { | |||
| 
 | ||||
|     if (process_hitags_common_args(ctx, &packet) < 0) return PM3_EINVARG; | ||||
| 
 | ||||
|     uint32_t page = arg_get_int_def(ctx, 5, 0); | ||||
|     uint32_t page = arg_get_int_def(ctx, 6, 0); | ||||
| 
 | ||||
|     if (page > 255) { | ||||
|         PrintAndLogEx(WARNING, "Page address Invalid."); | ||||
|         return PM3_EINVARG; | ||||
|     } | ||||
| 
 | ||||
|     uint32_t count = arg_get_int_def(ctx, 6, 1); | ||||
|     uint32_t count = arg_get_int_def(ctx, 7, 1); | ||||
| 
 | ||||
|     if (count > HITAGS_MAX_PAGES) { | ||||
|         PrintAndLogEx(WARNING, "No more than 64 pages can be read at once."); | ||||
|  | @ -438,6 +461,7 @@ static int CmdLFHitagSWrite(const char *Cmd) { | |||
|         arg_str0(NULL, "nrar", "<hex>", "nonce / answer writer, 8 hex bytes"), | ||||
|         arg_lit0(NULL, "crypto", "crypto mode"), | ||||
|         arg_str0("k", "key", "<hex>", "pwd or key, 4 or 6 hex bytes"), | ||||
|         arg_int0("m", "mode", "<dec>", "response protocol mode. 0 (Standard 00110), 1 (Advanced 11000), 2 (Advanced 11001), 3 (Fast Advanced 11010) (def: 3)"), | ||||
|         arg_int1("p", "page", "<dec>", "page address to write to"), | ||||
|         arg_str1("d", "data", "<hex>", "data, 4 hex bytes"), | ||||
|         arg_param_end | ||||
|  | @ -448,12 +472,12 @@ static int CmdLFHitagSWrite(const char *Cmd) { | |||
| 
 | ||||
|     if (process_hitags_common_args(ctx, &packet) < 0) return PM3_EINVARG; | ||||
| 
 | ||||
|     int page = arg_get_int_def(ctx, 5, 0); | ||||
|     int page = arg_get_int_def(ctx, 6, 0); | ||||
| 
 | ||||
|     uint8_t data[HITAGS_PAGE_SIZE]; | ||||
|     int data_len = 0; | ||||
| 
 | ||||
|     int res = CLIParamHexToBuf(arg_get_str(ctx, 6), data, HITAGS_PAGE_SIZE, &data_len); | ||||
|     int res = CLIParamHexToBuf(arg_get_str(ctx, 7), data, HITAGS_PAGE_SIZE, &data_len); | ||||
|     if (res != 0) { | ||||
|         CLIParserFree(ctx); | ||||
|         return PM3_EINVARG; | ||||
|  | @ -538,7 +562,7 @@ static int CmdLFHitagSSim(const char *Cmd) { | |||
|     CLIParserFree(ctx); | ||||
| 
 | ||||
|     clearCommandBuffer(); | ||||
|     SendCommandNG(CMD_LF_HITAGS_SIMULATE, NULL, 0); | ||||
|     SendCommandMIX(CMD_LF_HITAGS_SIMULATE, false, 0, 0, NULL, 0); | ||||
|     return PM3_SUCCESS; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -65,30 +65,6 @@ typedef enum { | |||
|     HT2_LAST_CMD              = HT2F_UID_ONLY, | ||||
| } PACKED hitag_function; | ||||
| 
 | ||||
| typedef struct { | ||||
|     hitag_function cmd; | ||||
|     uint8_t page; | ||||
|     uint8_t page_count; | ||||
|     uint8_t data[HITAGS_PAGE_SIZE]; | ||||
|     uint8_t NrAr[HITAG_NRAR_SIZE]; | ||||
|     // unaligned access to key as uint64_t will abort.
 | ||||
|     // todo: Why does the compiler without -munaligned-access generate unaligned-access code in the first place?
 | ||||
|     uint8_t key[HITAG_CRYPTOKEY_SIZE] __attribute__((aligned(4))); | ||||
|     uint8_t pwd[HITAG_PASSWORD_SIZE]; | ||||
| 
 | ||||
|     // Hitag 1 section.
 | ||||
|     // will reuse pwd or key field.
 | ||||
|     uint8_t key_no; | ||||
|     uint8_t logdata_0[4]; | ||||
|     uint8_t logdata_1[4]; | ||||
|     uint8_t nonce[4]; | ||||
| } PACKED lf_hitag_data_t; | ||||
| 
 | ||||
| typedef struct { | ||||
|     int status; | ||||
|     uint8_t data[256]; | ||||
| } PACKED lf_hitag_crack_response_t; | ||||
| 
 | ||||
| //---------------------------------------------------------
 | ||||
| // Hitag S
 | ||||
| //---------------------------------------------------------
 | ||||
|  | @ -111,15 +87,6 @@ typedef enum TAG_STATE { | |||
|     HT_WRITING_BLOCK_DATA | ||||
| } TSATE; | ||||
| 
 | ||||
| //number of start-of-frame bits
 | ||||
| typedef enum SOF_TYPE { | ||||
|     HT_STANDARD = 0, | ||||
|     HT_ADVANCED, | ||||
|     HT_FAST_ADVANCED, | ||||
|     HT_ONE, | ||||
|     HT_NO_BITS | ||||
| } stype; | ||||
| 
 | ||||
| typedef struct { | ||||
|     // con0
 | ||||
|     uint8_t MEMT : 2; | ||||
|  | @ -156,7 +123,6 @@ struct hitagS_tag { | |||
|     TSATE    tstate;    // tag-state
 | ||||
| 
 | ||||
|     int      max_page; | ||||
|     stype    mode; | ||||
| 
 | ||||
|     union { | ||||
|         uint8_t pages[64][4]; | ||||
|  | @ -177,6 +143,33 @@ struct hitagS_tag { | |||
| 
 | ||||
| } PACKED; | ||||
| 
 | ||||
| typedef struct { | ||||
|     hitag_function cmd; | ||||
|     uint8_t page; | ||||
|     uint8_t page_count; | ||||
|     uint8_t data[HITAGS_PAGE_SIZE]; | ||||
|     uint8_t NrAr[HITAG_NRAR_SIZE]; | ||||
|     // unaligned access to key as uint64_t will abort.
 | ||||
|     // todo: Why does the compiler without -munaligned-access generate unaligned-access code in the first place?
 | ||||
|     uint8_t key[HITAG_CRYPTOKEY_SIZE] __attribute__((aligned(4))); | ||||
|     uint8_t pwd[HITAG_PASSWORD_SIZE]; | ||||
| 
 | ||||
|     // Hitag 1 section.
 | ||||
|     // will reuse pwd or key field.
 | ||||
|     uint8_t key_no; | ||||
|     uint8_t logdata_0[4]; | ||||
|     uint8_t logdata_1[4]; | ||||
|     uint8_t nonce[4]; | ||||
| 
 | ||||
|     //Hitag s section
 | ||||
|     uint8_t mode; | ||||
| } PACKED lf_hitag_data_t; | ||||
| 
 | ||||
| typedef struct { | ||||
|     int status; | ||||
|     uint8_t data[256]; | ||||
| } PACKED lf_hitag_crack_response_t; | ||||
| 
 | ||||
| typedef struct { | ||||
|     union { | ||||
|         uint8_t asBytes[HITAGS_PAGE_SIZE]; | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue