#include "legicrf.h"
static struct legic_frame {
- int bits;
+ uint8_t bits;
uint32_t data;
} current_frame;
int legic_read_byte(int byte_index, int cmd_sz) {
- uint8_t byte = 0, crc = 0, calcCrc = 0;
+ uint8_t byte = 0; //, crc = 0, calcCrc = 0;
uint32_t cmd = (byte_index << 1) | LEGIC_READ;
// (us)| ticks
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);
- if( calcCrc != crc ) {
- Dbprintf("!!! crc mismatch: expected %x but got %x !!!", calcCrc, crc);
- return -1;
- }
+ // if( calcCrc != crc ) {
+ // Dbprintf("!!! crc mismatch: expected %x but got %x !!!", calcCrc, crc);
+ // return -1;
+ // }
legic_prng_forward(4);
WaitTicks(40);
int LegicRfReader(int offset, int bytes, int iv) {
uint16_t byte_index = 0;
- uint8_t cmd_sz = 0, isOK = 1;
- int card_sz = 0;
-
+ uint8_t isOK = 1;
+ legic_card_select_t card;
+
LegicCommonInit();
-
- uint32_t tag_type = setup_phase_reader(iv);
+ if ( legic_select_card(&card) ) {
+ isOK = 0;
+ goto OUT;
+ }
+
switch_off_tag_rwd();
- switch(tag_type) {
- case 0x0d:
- if ( MF_DBGLEVEL >= 2) DbpString("MIM22 card found, reading card");
- cmd_sz = 6;
- card_sz = 22;
- break;
- case 0x1d:
- if ( MF_DBGLEVEL >= 2) DbpString("MIM256 card found, reading card");
- cmd_sz = 9;
- card_sz = 256;
- break;
- case 0x3d:
- if ( MF_DBGLEVEL >= 2) DbpString("MIM1024 card found, reading card");
- cmd_sz = 11;
- card_sz = 1024;
- break;
- default:
- if ( MF_DBGLEVEL >= 1) Dbprintf("Unknown card format: %x", tag_type);
- isOK = 0;
- goto OUT;
- break;
- }
if (bytes == -1)
- bytes = card_sz;
+ bytes = card.cardsize;
- if (bytes + offset >= card_sz)
- bytes = card_sz - offset;
+ if (bytes + offset >= card.cardsize)
+ bytes = card.cardsize - offset;
// 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);
+ int r = legic_read_byte(byte_index + offset, card.cmdsize);
if (r == -1 || BUTTON_PRESS()) {
if ( MF_DBGLEVEL >= 3) DbpString("operation aborted");
isOK = 0;
goto OUT;
}
- cardmem[++byte_index] = r;
+ cardmem[byte_index++] = r;
WDT_HIT();
}
if ( MF_DBGLEVEL >= 1) DbpString("write successful");
}
-void LegicRfInfo(void){
+int legic_select_card(legic_card_select_t *p_card){
- LegicCommonInit();
- uint32_t tag_type = setup_phase_reader(0x1);
- uint8_t cmd_sz = 0;
- uint16_t card_sz = 0;
+ if ( p_card == NULL ) return 1;
- switch(tag_type) {
+ p_card->tagtype = setup_phase_reader(0x1);
+
+ switch(p_card->tagtype) {
case 0x0d:
- cmd_sz = 6;
- card_sz = 22;
+ p_card->cmdsize = 6;
+ p_card->cardsize = 22;
break;
case 0x1d:
- cmd_sz = 9;
- card_sz = 256;
+ p_card->cmdsize = 9;
+ p_card->cardsize = 256;
break;
case 0x3d:
- cmd_sz = 11;
- card_sz = 1024;
+ p_card->cmdsize = 11;
+ p_card->cardsize = 1024;
break;
default:
- cmd_send(CMD_ACK,0,0,0,0,0);
- goto OUT;
+ p_card->cmdsize = 0;
+ p_card->cardsize = 0;
+ return 2;
+ break;
+ }
+ return 0;
+}
+
+void LegicRfInfo(void){
+
+ uint8_t buf[sizeof(legic_card_select_t)] = {0x00};
+ legic_card_select_t *card = (legic_card_select_t*) buf;
+
+ LegicCommonInit();
+
+ if ( legic_select_card(card) ) {
+ cmd_send(CMD_ACK,0,0,0,0,0);
+ goto OUT;
}
// read UID bytes.
- uint8_t uid[] = {0,0,0,0};
- for ( uint8_t i = 0; i < sizeof(uid); ++i) {
- int r = legic_read_byte(i, cmd_sz);
+ for ( uint8_t i = 0; i < sizeof(card->uid); ++i) {
+ int r = legic_read_byte(i, card->cmdsize);
if ( r == -1 ) {
cmd_send(CMD_ACK,0,0,0,0,0);
goto OUT;
}
- uid[i] = r & 0xFF;
+ card->uid[i] = r & 0xFF;
}
- cmd_send(CMD_ACK,1,card_sz,0,uid,sizeof(uid));
-OUT:
+ cmd_send(CMD_ACK, 1 ,0 , 0, buf, sizeof(legic_card_select_t));
+
+OUT:
switch_off_tag_rwd();
LEDsoff();
-
}
/* Handle (whether to respond) a frame in tag mode
-//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
// (c) 2009 Henryk Plötz <henryk@ploetzli.ch>
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
#include "legic_prng.h" // legic PRNG impl
#include "crc.h" // legic crc-4
#include "ticks.h" // timers
+#include "legic.h" // legic_card_select_t struct
extern void LegicRfSimulate(int phase, int frame, int reqresp);
extern int LegicRfReader(int offset, int bytes, int iv);
void frame_send_tag(uint16_t response, uint8_t bits, uint8_t crypt);
void frame_sendAsReader(uint32_t data, uint8_t bits);
-int ice_legic_select_card();
+int legic_select_card(legic_card_select_t *p_card);
void ice_legic_setup();
#endif /* __LEGICRF_H */
static int CmdHelp(const char *Cmd);
-#define SESSION_IV 0x55
#define MAX_LENGTH 1024
int usage_legic_calccrc8(void){
sscanf(Cmd, "%x %x %x", &offset, &len, &IV);
// OUT-OF-BOUNDS check
- if(len + offset > MAX_LENGTH) len = MAX_LENGTH - offset;
+ if ( len + offset > MAX_LENGTH ) {
+ len = MAX_LENGTH - offset;
+ PrintAndLog("Out-of-bound, shorten len to %d",len);
+ }
if ( (IV & 0x7F) != IV ){
IV &= 0x7F;
PrintAndLog("Truncating IV to 7bits");
}
+
if ( (IV & 1) == 0 ){
- IV |= 0x01; // IV must be odd
+ IV |= 0x01;
PrintAndLog("LSB of IV must be SET");
}
+
PrintAndLog("Using IV: 0x%02x", IV);
UsbCommand c = {CMD_READER_LEGIC_RF, {offset, len, IV}};
clearCommandBuffer();
SendCommand(&c);
UsbCommand resp;
- if (WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {
- uint8_t isOK = resp.arg[0] & 0xFF;
- uint16_t tagtype = resp.arg[1] & 0xFFF;
- if ( isOK ) {
- PrintAndLog(" UID : %s", sprint_hex(resp.d.asBytes, 4));
- switch(tagtype) {
- case 22: PrintAndLog("MIM22 card (22bytes)"); break;
- case 256: PrintAndLog("MIM256 card (256bytes)"); break;
- case 1024: PrintAndLog("MIM1024 card (1024bytes)"); break;
- default: {
- PrintAndLog("Unknown card format: %x", tagtype);
- return 1;
- }
- }
- } else {
- if ( verbose ) PrintAndLog("legic card select failed");
- return 1;
- }
- } else {
+ if (!WaitForResponseTimeout(CMD_ACK, &resp, 500)) {
if ( verbose ) PrintAndLog("command execution time out");
return 1;
}
+
+ uint8_t isOK = resp.arg[0] & 0xFF;
+ if ( !isOK ) {
+ if ( verbose ) PrintAndLog("legic card select failed");
+ return 1;
+ }
+
+ legic_card_select_t card;
+ memcpy(&card, (legic_card_select_t *)resp.d.asBytes, sizeof(legic_card_select_t));
+
+ PrintAndLog(" UID : %s", sprint_hex(card.uid, sizeof(card.uid)));
+ switch(card.cardsize) {
+ case 22:
+ case 256:
+ case 1024:
+ PrintAndLog(" TYPE : MIM%d card (%d bytes)", card.cardsize, card.cardsize); break;
+ default: {
+ PrintAndLog("Unknown card format: %d", card.cardsize);
+ return 1;
+ }
+ }
return 0;
}
int CmdLegicInfo(const char *Cmd){
#include "util.h"
#include "crc.h"
#include "legic_prng.h"
+#include "legic.h" // legic_card_select_t struct
int CmdHFLegic(const char *Cmd);
}
void crc_clear(crc_t *crc) {
+
crc->state = crc->initial_value & crc->mask;
if (crc->refin)
crc->state = reflect(crc->state, crc->order);
void crc_update(crc_t *crc, uint32_t indata, int data_width){
+ uint32_t poly = crc->polynom;
+
+ // if requested, return the initial CRC */
+ if (indata == 0)
+ return crc->initial_value;
+
//reflected
- if (crc->refin) indata = reflect(indata, data_width);
+ if (crc->refin)
+ indata = reflect(indata, data_width);
// Bring the next byte into the remainder.
crc->state ^= indata << (crc->order - data_width);
- for( uint8_t bit = data_width; bit > 0; --bit) {
-
-
+ for( uint8_t bit = data_width; bit > 0; --bit) {
// Try to divide the current data bit.
if (crc->state & crc->topbit)
- crc->state = (crc->state << 1) ^ crc->polynom;
+ crc->state = (crc->state << 1) ^ poly;
else
crc->state = (crc->state << 1);
}
+ return crc ^ model->xorout;
}
void crc_update2(crc_t *crc, uint32_t data, int data_width)
{
- if (crc->refin) data = reflect(data, data_width);
+ if (crc->refin)
+ data = reflect(data, data_width);
int i;
for(i=0; i<data_width; i++) {
uint8_t mem_config; //[13]
uint8_t eas; //[14]
uint8_t fuses; //[15]
-}picopass_conf_block;
+} picopass_conf_block;
typedef struct {
uint8_t key_d[8];
uint8_t key_c[8];
uint8_t app_issuer_area[8];
-
-}picopass_hdr;
+} picopass_hdr;
uint8_t isset(uint8_t val, uint8_t mask) {
return (val & mask);
--- /dev/null
+//-----------------------------------------------------------------------------
+// (c) 2016 Iceman
+//
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// LEGIC type prototyping
+//-----------------------------------------------------------------------------
+
+#ifndef _LEGIC_H_
+#define _LEGIC_H_
+
+#include "common.h"
+
+//-----------------------------------------------------------------------------
+// LEGIC
+//-----------------------------------------------------------------------------
+typedef struct {
+ uint8_t uid[4];
+ uint32_t tagtype;
+ uint8_t cmdsize;
+ uint16_t cardsize;
+} legic_card_select_t;
+
+#endif // _LEGIC_H_