CHG: 'hf legic read' the device side timings is starting to look much better. HUGE Thanks to @will-rbnt for endless checks and logic analyser feedback. Without his effort this would not work. What does work? We can now use ANY IV in legic. The PM3 Master version is flawed, will only work with IV=0x55.
---still broke--- my crc implementation.. I know I'm about to look into it.
#define RWD_TIME_1 120 // READER_TIME_PAUSE 20us off, 80us on = 100us 80 * 1.5 == 120ticks
#define RWD_TIME_0 60 // READER_TIME_PAUSE 20us off, 40us on = 60us 40 * 1.5 == 60ticks
#define RWD_TIME_PAUSE 30 // 20us == 20 * 1.5 == 30ticks */
#define RWD_TIME_1 120 // READER_TIME_PAUSE 20us off, 80us on = 100us 80 * 1.5 == 120ticks
#define RWD_TIME_0 60 // READER_TIME_PAUSE 20us off, 40us on = 60us 40 * 1.5 == 60ticks
#define RWD_TIME_PAUSE 30 // 20us == 20 * 1.5 == 30ticks */
-#define TAG_BIT_PERIOD 150 // 100us == 100 * 1.5 == 150ticks
+#define TAG_BIT_PERIOD 143 // 100us == 100 * 1.5 == 150ticks
#define TAG_FRAME_WAIT 495 // 330us from READER frame end to TAG frame start. 330 * 1.5 == 495
#define RWD_TIME_FUZZ 20 // rather generous 13us, since the peak detector + hysteresis fuzz quite a bit
#define TAG_FRAME_WAIT 495 // 330us from READER frame end to TAG frame start. 330 * 1.5 == 495
#define RWD_TIME_FUZZ 20 // rather generous 13us, since the peak detector + hysteresis fuzz quite a bit
uint8_t i = bits, edges = 0;
uint16_t lsfr = 0;
uint8_t i = bits, edges = 0;
uint16_t lsfr = 0;
- uint32_t the_bit = 1, next_bit_at = 0, data;
+ uint32_t the_bit = 1, next_bit_at = 0, data = 0;
int old_level = 0, level = 0;
int old_level = 0, level = 0;
// calibrate the prng.
legic_prng_forward(2);
// calibrate the prng.
legic_prng_forward(2);
-
- // precompute the cipher
uint8_t prngstart = legic_prng_count() ;
uint8_t prngstart = legic_prng_count() ;
data = lsfr = legic_prng_get_bits(bits);
//FIXED time between sending frame and now listening frame. 330us
// 387 = 0x19 0001 1001
data = lsfr = legic_prng_get_bits(bits);
//FIXED time between sending frame and now listening frame. 330us
// 387 = 0x19 0001 1001
- // 480 = 0x19
- // 500 = 0x1C 0001 1100
uint32_t starttime = GET_TICKS;
//uint16_t mywait = TAG_FRAME_WAIT - (starttime - sendFrameStop);
//uint16_t mywait = 495 - (starttime - sendFrameStop);
if ( bits == 6) {
uint32_t starttime = GET_TICKS;
//uint16_t mywait = TAG_FRAME_WAIT - (starttime - sendFrameStop);
//uint16_t mywait = 495 - (starttime - sendFrameStop);
if ( bits == 6) {
- //Dbprintf("6 WAIT %d", 495 - 9 - 9 );
- WaitTicks( 495 - 9 - 9 );
+ //WaitTicks( 495 - 9 - 9 );
+ WaitTicks( 475 );
} else {
//Dbprintf("x WAIT %d", mywait );
//WaitTicks( mywait );
} else {
//Dbprintf("x WAIT %d", mywait );
//WaitTicks( mywait );
while ( i-- ){
edges = 0;
while ( i-- ){
edges = 0;
while ( GET_TICKS < next_bit_at) {
level = (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_DIN);
while ( GET_TICKS < next_bit_at) {
level = (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_DIN);
++edges;
old_level = level;
++edges;
old_level = level;
-
- if(edges > 20 && adjust == 0) {
- next_bit_at -= 15;
- adjust = 1;
- }
}
next_bit_at += TAG_BIT_PERIOD;
}
next_bit_at += TAG_BIT_PERIOD;
uint8_t cmdbytes[] = {
bits,
uint8_t cmdbytes[] = {
bits,
- BYTEx(data,0),
- BYTEx(data,1),
- BYTEx(data, 0) ^ BYTEx(lsfr,0),
- BYTEx(data, 1) ^ BYTEx(lsfr,1),
+ BYTEx(data, 0),
+ BYTEx(data, 1),
+ BYTEx(data, 0) ^ BYTEx(lsfr, 0),
+ BYTEx(data, 1) ^ BYTEx(lsfr, 1),
prngstart,
legic_prng_count()
};
prngstart,
legic_prng_count()
};
// Switch on carrier and let the tag charge for 1ms
HIGH(GPIO_SSC_DOUT);
// Switch on carrier and let the tag charge for 1ms
HIGH(GPIO_SSC_DOUT);
frame_receiveAsReader(¤t_frame, 6);
frame_receiveAsReader(¤t_frame, 6);
- // fixed delay before sending ack.
- WaitTicks(366); // 244us
- legic_prng_forward(1); //240us / 100 == 2.4 iterations
+ // 292us (438t) - fixed delay before sending ack.
+ // minus log and stuff 100tick?
+ WaitTicks(338);
+ legic_prng_forward(3);
// Send obsfuscated acknowledgment frame.
// 0x19 = 0x18 MIM22, 0x01 LSB READCMD
// Send obsfuscated acknowledgment frame.
// 0x19 = 0x18 MIM22, 0x01 LSB READCMD
case 0x3D: frame_sendAsReader(0x39, 6); break;
default: break;
}
case 0x3D: frame_sendAsReader(0x39, 6); break;
default: break;
}
+
+ legic_prng_forward(2);
return current_frame.data;
}
return current_frame.data;
}
// (us)| ticks
// -------------
// 330 | 495
// (us)| ticks
// -------------
// 330 | 495
- // 460 | 690
- // 258 | 387
- WaitTicks(495);
- legic_prng_forward(3); // 460 / 100 = 4.6 iterations
frame_sendAsReader(cmd, cmd_sz);
frame_receiveAsReader(¤t_frame, 12);
byte = BYTEx(current_frame.data, 0);
frame_sendAsReader(cmd, cmd_sz);
frame_receiveAsReader(¤t_frame, 12);
byte = BYTEx(current_frame.data, 0);
calcCrc = legic4Crc(LEGIC_READ, byte_index, byte, cmd_sz);
crc = BYTEx(current_frame.data, 1);
calcCrc = legic4Crc(LEGIC_READ, byte_index, byte, cmd_sz);
crc = BYTEx(current_frame.data, 1);
Dbprintf("!!! crc mismatch: expected %x but got %x !!!", calcCrc, crc);
return -1;
}
Dbprintf("!!! crc mismatch: expected %x but got %x !!!", calcCrc, crc);
return -1;
}
+
+ legic_prng_forward(4);
+ WaitTicks(40);
// Start setup and read bytes.
setup_phase_reader(iv);
// Start setup and read bytes.
setup_phase_reader(iv);
LED_B_ON();
while (byte_index < bytes) {
int r = legic_read_byte(byte_index + offset, cmd_sz);
LED_B_ON();
while (byte_index < bytes) {
int r = legic_read_byte(byte_index + offset, cmd_sz);
void LegicRfInfo(void){
LegicCommonInit();
void LegicRfInfo(void){
LegicCommonInit();
- uint32_t tag_type = setup_phase_reader(0x55);
+ uint32_t tag_type = setup_phase_reader(0x1);
uint8_t cmd_sz = 0;
uint16_t card_sz = 0;
uint8_t cmd_sz = 0;
uint16_t card_sz = 0;
//-----------------------------------------------------------------------------
// Timers, Clocks functions used in LF or Legic where you would need detailed time.
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Timers, Clocks functions used in LF or Legic where you would need detailed time.
//-----------------------------------------------------------------------------
#include "ticks.h"
// attempt at high resolution microsecond timer
#include "ticks.h"
// attempt at high resolution microsecond timer
oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01);
}
uint8_t parityBits = parityBytes[j>>3];
oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01);
}
uint8_t parityBits = parityBytes[j>>3];
- if (protocol != ISO_14443B && protocol != ISO_7816_4 && (isResponse || protocol == ISO_14443A) && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) {
+ if (protocol != LEGIC && protocol != ISO_14443B && protocol != ISO_7816_4 && (isResponse || protocol == ISO_14443A) && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) {
snprintf(line[j/16]+(( j % 16) * 4),110, "%02x! ", frame[j]);
} else {
snprintf(line[j/16]+(( j % 16) * 4),110, "%02x ", frame[j]);
snprintf(line[j/16]+(( j % 16) * 4),110, "%02x! ", frame[j]);
} else {
snprintf(line[j/16]+(( j % 16) * 4),110, "%02x ", frame[j]);
IV |= 0x01; // IV must be odd
PrintAndLog("LSB of IV must be SET");
}
IV |= 0x01; // IV must be odd
PrintAndLog("LSB of IV must be SET");
}
- PrintAndLog("Current IV: 0x%02x", IV);
+ PrintAndLog("Using IV: 0x%02x", IV);
- // get some prng bytes from
- uint8_t temp[32];
- legic_prng_init(IV);
- for ( uint8_t j = 0; j < sizeof(temp); ++j) {
- temp[j] = legic_prng_get_bit(1);
- legic_prng_forward(1);
- //PrintAndLog("PRNG: %s", sprint_hex(temp, sizeof(temp)));
- }
- PrintAndLog("PRNG: %s", sprint_bin(temp, sizeof(temp)));
-
UsbCommand c = {CMD_READER_LEGIC_RF, {offset, len, IV}};
clearCommandBuffer();
SendCommand(&c);
UsbCommand c = {CMD_READER_LEGIC_RF, {offset, len, IV}};
clearCommandBuffer();
SendCommand(&c);