int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int len){ /* uint32_t nt; // tag challenge uint32_t nr_enc; // encrypted reader challenge uint32_t ar_enc; // encrypted reader response uint32_t at_enc; // encrypted tag response */ struct Crypto1State *pcs = NULL; ks2 = ar_enc ^ prng_successor(nt, 64); ks3 = at_enc ^ prng_successor(nt, 96); PrintAndLog("Decrypting data with:"); PrintAndLog(" nt: %08x",nt); PrintAndLog(" ar_enc: %08x",ar_enc); PrintAndLog(" at_enc: %08x",at_enc); PrintAndLog("\nEncrypted data: [%s]", sprint_hex(data,len) ); pcs = lfsr_recovery64(ks2, ks3); mf_crypto1_decrypt(pcs, data, len, FALSE); PrintAndLog("Decrypted data: [%s]", sprint_hex(data,len) ); crypto1_destroy(pcs); return 0; }
int mfCSetUID(uint8_t *uid, uint8_t *atqa, uint8_t *sak, uint8_t *oldUID, bool wantWipe) { uint8_t oldblock0[16] = {0x00}; uint8_t block0[16] = {0x00}; int old = mfCGetBlock(0, oldblock0, CSETBLOCK_SINGLE_OPER); if (old == 0) { memcpy(block0, oldblock0, 16); PrintAndLog("old block 0: %s", sprint_hex(block0,16)); } else { PrintAndLog("Couldn't get old data. Will write over the last bytes of Block 0."); } // fill in the new values // UID memcpy(block0, uid, 4); // Mifare UID BCC block0[4] = block0[0]^block0[1]^block0[2]^block0[3]; // mifare classic SAK(byte 5) and ATQA(byte 6 and 7, reversed) if (sak!=NULL) block0[5]=sak[0]; if (atqa!=NULL) { block0[6]=atqa[1]; block0[7]=atqa[0]; } PrintAndLog("new block 0: %s", sprint_hex(block0,16)); return mfCSetBlock(0, block0, oldUID, wantWipe, CSETBLOCK_SINGLE_OPER); }
int mfCSetUID(uint8_t *uid, uint8_t *atqa, uint8_t *sak, uint8_t *oldUID, uint8_t wipecard) { uint8_t params = MAGIC_SINGLE; uint8_t block0[16]; memset(block0, 0x00, sizeof(block0)); int old = mfCGetBlock(0, block0, params); if (old == 0) PrintAndLog("old block 0: %s", sprint_hex(block0, sizeof(block0))); else PrintAndLog("Couldn't get old data. Will write over the last bytes of Block 0."); // fill in the new values // UID memcpy(block0, uid, 4); // Mifare UID BCC block0[4] = block0[0]^block0[1]^block0[2]^block0[3]; // mifare classic SAK(byte 5) and ATQA(byte 6 and 7, reversed) if ( sak != NULL ) block0[5]=sak[0]; if ( atqa != NULL ) { block0[6]=atqa[1]; block0[7]=atqa[0]; } PrintAndLog("new block 0: %s", sprint_hex(block0,16)); if ( wipecard ) params |= MAGIC_WIPE; if ( oldUID == NULL) params |= MAGIC_UID; return mfCSetBlock(0, block0, oldUID, params); }
int dm_bunnypair(char *path, u8 *old_output, u8 *seed, u8 *output) { int e; char *msg = steg_malloc(512); strcpy(msg, "bunnypair "); sprint_hex(msg + strlen(msg), old_output, BUNNY_ENTRY_BYTES); strcat(msg, " "); sprint_hex(msg + strlen(msg), seed, BUNNY_ENTRY_BYTES); strcat(msg, " "); sprint_hex(msg + strlen(msg), output, BUNNY_ENTRY_BYTES); e = dm_message(path, msg); steg_free(msg); return e; }
int pcf7931_printConfig() { PrintAndLog("Password (LSB first on bytes) : %s", sprint_hex( configPcf.Pwd, sizeof(configPcf.Pwd))); PrintAndLog("Tag initialization delay : %d us", configPcf.InitDelay); PrintAndLog("Offset low pulses width : %d us", configPcf.OffsetWidth); PrintAndLog("Offset low pulses position : %d us", configPcf.OffsetPosition); return 0; }
int dm_mount_aspect(substrate_t *substrate, u64 header_offset, u8 *header_key, char *name) { char *params; struct dm_task *task; task = dm_task_create(DM_DEVICE_CREATE); if(!task) { die("dm_task_create"); } if(!dm_task_set_name(task, name)) { die("dm_task_set_name"); } if(!dm_task_set_uuid(task, name)) { die("dm_task_set_uuid"); } params = steg_malloc(strlen(substrate->filename) + 4096); sprintf(params, "%s %zu ", substrate->filename, header_offset); sprint_hex(params + strlen(params), header_key, KEY_BYTES); if(!dm_task_add_target(task, 0, substrate->bytes, "steg", params)) { die("dm_task_add_target"); } if(!dm_task_run(task)) { die("dm_task_run"); } dm_task_destroy(task); steg_free(params); return 0; }
/* Prints the given number of bytes, one byte at a time in hex, no space. * Accepts: a pointer to char array to be printed * the number of bytes to be printed * Returns: Buffer with size 2 * num * NOTE: FREE THE HEXBYTES ARRAY AFTER USE */ struct Buffer *sprint_nbytes(unsigned char *bytes, int num) { struct Buffer *hbuf = (struct Buffer *)malloc_eoe(sizeof(struct Buffer)); hbuf->size = num; hbuf->cnt = (char *)malloc_eoe(2*num); char *si = hbuf->cnt; int j; for (j = 0; j < num; j++) { if (bytes[j] < 16) { sprintf(si, "0"); sprint_hex(bytes[j], si + 1); } else { sprint_hex(bytes[j] / 16, si); sprint_hex(bytes[j] % 16, si + 1); } si += 2; } return hbuf; }
int CmdLFNedapChk(const char *Cmd){ //301600714021BE uint8_t data[256] = { 0x30, 0x16, 0x00, 0x71, 0x40, 0x21, 0xBE}; int len = 0; param_gethex_ex(Cmd, 0, data, &len); len = ( len == 0 ) ? 5 : len>>1; PrintAndLogEx(NORMAL, "Input: [%d] %s", len, sprint_hex(data, len)); //uint8_t last = GetParity(data, EVEN, 62); //PrintAndLogEx(NORMAL, "TEST PARITY:: %d | %d ", DemodBuffer[62], last); uint8_t cl = 0x1D, ch = 0x1D, carry = 0; uint8_t al, bl, temp; for (int i =len; i >= 0; --i){ al = data[i]; for (int j = 8; j > 0; --j) { bl = al ^ ch; //PrintAndLogEx(NORMAL, "BL %02x | CH %02x \n", al, ch); carry = (cl & 0x80) ? 1 : 0; cl <<= 1; temp = (ch & 0x80) ? 1 : 0; ch = (ch << 1) | carry; carry = temp; carry = (al & 0x80) ? 1 : 0; al <<= 1; carry = (bl & 0x80) ? 1 : 0; bl <<= 1; if (carry) { cl ^= 0x21; ch ^= 0x10; } } } PrintAndLogEx(NORMAL, "Nedap checksum: 0x%X", ((ch << 8) | cl) ); return 0; }
// Simulation is still not working very good // helptext int CmdHF15Sim(const char *Cmd) { char cmdp = param_getchar(Cmd, 0); if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') return usage_15_sim(); uint8_t uid[8] = {0,0,0,0,0,0,0,0}; if (param_gethex(Cmd, 0, uid, 16)) { PrintAndLogEx(NORMAL, "UID must include 16 HEX symbols"); return 0; } PrintAndLogEx(NORMAL, "Starting simulating UID %s", sprint_hex(uid, sizeof(uid)) ); UsbCommand c = {CMD_SIMTAG_ISO_15693, {0, 0, 0}}; memcpy(c.d.asBytes, uid, 8); clearCommandBuffer(); SendCommand(&c); return 0; }
int CmdLegicCalcCrc8(const char *Cmd){ int len = strlen(Cmd); if ( len & 1 ) return usage_legic_calccrc8(); // add 1 for null terminator. uint8_t *data = malloc(len+1); if ( data == NULL ) return 1; if (param_gethex(Cmd, 0, data, len )) { free(data); return usage_legic_calccrc8(); } uint32_t checksum = CRC8Legic(data, len/2); PrintAndLog("Bytes: %s || CRC8: %X", sprint_hex(data, len/2), checksum ); free(data); return 0; }
char *sprint_hex_ascii(const uint8_t *data, const size_t len) { static char buf[1024]; char *tmp = buf; memset(buf, 0x00, 1024); size_t max_len = (len > 255) ? 255 : len; // max 255 bytes * 3 + 2 characters = 767 in buffer sprintf(tmp, "%.765s| ", sprint_hex(data, max_len) ); size_t i = 0; size_t pos = (max_len * 3)+2; // add another 255 characters ascii = 1020 characters of buffer used while(i < max_len) { char c = data[i]; if ( (c < 32) || (c == 127)) c = '.'; sprintf(tmp+pos+i, "%c", c); ++i; } return buf; }
/* * Authors: Weiyan Lin * * Purpose: It sends packet from the server * * Expected input: It takes respond packet from the result of cmd_buy and handle_buy * * * Implementation details: * It forms the send packet then sends it. * If the client of the user or of the Authentication Center * is wrong, the send_tcp_data would * use sprint_hex() to print the data in char array */ void send_tcp_data( int client, void *data, int datalen) { if (client) { ssize_t bytes_sent = send(client, data, datalen, 0); if (errno == EPIPE) { close(client); vending_exit_with_error("pipe error\n",NULL); } else if (bytes_sent < 0) { close(client); vending_exit_with_error("send failed",NULL); } } else { sprint_hex(data, datalen); } }
//this function sends a generic data buffer via tcp void send_tcp_data(FILE* rx, FILE *tx, void *data, int datalen) { if (tx) { size_t bytes_sent = fwrite(data, 1, datalen, tx); if (errno == EPIPE) { fclose(tx); fclose(rx); exit_with_error("pipe error\n"); } else if (bytes_sent < 0) { fclose(tx); fclose(rx); exit_with_error("send failed"); } fflush(tx); } else { sprint_hex((uint8_t *)data, datalen); } }
void ManchesterDiffDecodedString(const uint8_t* bitstream, size_t len, uint8_t invert){ /* * We have a bitstream of "01" ("1") or "10" ("0") * parse it into final decoded bitstream */ int i, j, warnings; uint8_t decodedArr[(len/2)+1]; j = warnings = 0; uint8_t lastbit = 0; for (i = 0; i < len; i += 2) { uint8_t first = bitstream[i]; uint8_t second = bitstream[i+1]; if ( first == second ) { ++i; ++warnings; if (warnings > 10) { PrintAndLog("Error: too many decode errors, aborting."); return; } } else if ( lastbit != first ) { decodedArr[j++] = 0 ^ invert; } else { decodedArr[j++] = 1 ^ invert; } lastbit = second; } PrintAndLog("%s", sprint_hex(decodedArr, j)); }
int CmdHF14AReader(const char *Cmd) { UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0}}; SendCommand(&c); UsbCommand resp; WaitForResponse(CMD_ACK,&resp); iso14a_card_select_t card; memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); uint64_t select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS if(select_status == 0) { PrintAndLog("iso14443a card select failed"); // disconnect c.arg[0] = 0; c.arg[1] = 0; c.arg[2] = 0; SendCommand(&c); return 0; } PrintAndLog("ATQA : %02x %02x", card.atqa[1], card.atqa[0]); PrintAndLog(" UID : %s", sprint_hex(card.uid, card.uidlen)); PrintAndLog(" SAK : %02x [%d]", card.sak, resp.arg[0]); // Double & triple sized UID, can be mapped to a manufacturer. // HACK: does this apply for Ultralight cards? if ( card.uidlen > 4 ) { PrintAndLog("MANUFACTURER : %s", getTagInfo(card.uid[0])); } switch (card.sak) { case 0x00: PrintAndLog("TYPE : NXP MIFARE Ultralight | Ultralight C"); break; case 0x01: PrintAndLog("TYPE : NXP TNP3xxx Activision Game Appliance"); break; case 0x04: PrintAndLog("TYPE : NXP MIFARE (various !DESFire !DESFire EV1)"); break; case 0x08: PrintAndLog("TYPE : NXP MIFARE CLASSIC 1k | Plus 2k SL1"); break; case 0x09: PrintAndLog("TYPE : NXP MIFARE Mini 0.3k"); break; case 0x10: PrintAndLog("TYPE : NXP MIFARE Plus 2k SL2"); break; case 0x11: PrintAndLog("TYPE : NXP MIFARE Plus 4k SL2"); break; case 0x18: PrintAndLog("TYPE : NXP MIFARE Classic 4k | Plus 4k SL1"); break; case 0x20: PrintAndLog("TYPE : NXP MIFARE DESFire 4k | DESFire EV1 2k/4k/8k | Plus 2k/4k SL3 | JCOP 31/41"); break; case 0x24: PrintAndLog("TYPE : NXP MIFARE DESFire | DESFire EV1"); break; case 0x28: PrintAndLog("TYPE : JCOP31 or JCOP41 v2.3.1"); break; case 0x38: PrintAndLog("TYPE : Nokia 6212 or 6131 MIFARE CLASSIC 4K"); break; case 0x88: PrintAndLog("TYPE : Infineon MIFARE CLASSIC 1K"); break; case 0x98: PrintAndLog("TYPE : Gemplus MPCOS"); break; default: ; } // try to request ATS even if tag claims not to support it if (select_status == 2) { uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0 c.arg[0] = ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT; c.arg[1] = 2; c.arg[2] = 0; memcpy(c.d.asBytes, rats, 2); SendCommand(&c); WaitForResponse(CMD_ACK,&resp); memcpy(&card.ats, resp.d.asBytes, resp.arg[0]); card.ats_len = resp.arg[0]; // note: ats_len includes CRC Bytes } if(card.ats_len >= 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes bool ta1 = 0, tb1 = 0, tc1 = 0; int pos; if (select_status == 2) { PrintAndLog("SAK incorrectly claims that card doesn't support RATS"); } PrintAndLog(" ATS : %s", sprint_hex(card.ats, card.ats_len)); PrintAndLog(" - TL : length is %d bytes", card.ats[0]); if (card.ats[0] != card.ats_len - 2) { PrintAndLog("ATS may be corrupted. Length of ATS (%d bytes incl. 2 Bytes CRC) doesn't match TL", card.ats_len); } if (card.ats[0] > 1) { // there is a format byte (T0) ta1 = (card.ats[1] & 0x10) == 0x10; tb1 = (card.ats[1] & 0x20) == 0x20; tc1 = (card.ats[1] & 0x40) == 0x40; int16_t fsci = card.ats[1] & 0x0f; PrintAndLog(" - T0 : TA1 is%s present, TB1 is%s present, " "TC1 is%s present, FSCI is %d (FSC = %ld)", (ta1 ? "" : " NOT"), (tb1 ? "" : " NOT"), (tc1 ? "" : " NOT"), fsci, fsci < 5 ? (fsci - 2) * 8 : fsci < 8 ? (fsci - 3) * 32 : fsci == 8 ? 256 : -1 ); } pos = 2; if (ta1) { char dr[16], ds[16]; dr[0] = ds[0] = '\0'; if (card.ats[pos] & 0x10) strcat(ds, "2, "); if (card.ats[pos] & 0x20) strcat(ds, "4, "); if (card.ats[pos] & 0x40) strcat(ds, "8, "); if (card.ats[pos] & 0x01) strcat(dr, "2, "); if (card.ats[pos] & 0x02) strcat(dr, "4, "); if (card.ats[pos] & 0x04) strcat(dr, "8, "); if (strlen(ds) != 0) ds[strlen(ds) - 2] = '\0'; if (strlen(dr) != 0) dr[strlen(dr) - 2] = '\0'; PrintAndLog(" - TA1 : different divisors are%s supported, " "DR: [%s], DS: [%s]", (card.ats[pos] & 0x80 ? " NOT" : ""), dr, ds); pos++; } if (tb1) { uint32_t sfgi = card.ats[pos] & 0x0F; uint32_t fwi = card.ats[pos] >> 4; PrintAndLog(" - TB1 : SFGI = %d (SFGT = %s%ld/fc), FWI = %d (FWT = %ld/fc)", (sfgi), sfgi ? "" : "(not needed) ", sfgi ? (1 << 12) << sfgi : 0, fwi, (1 << 12) << fwi ); pos++; } if (tc1) { PrintAndLog(" - TC1 : NAD is%s supported, CID is%s supported", (card.ats[pos] & 0x01) ? "" : " NOT", (card.ats[pos] & 0x02) ? "" : " NOT"); pos++; } if (card.ats[0] > pos) { char *tip = ""; if (card.ats[0] - pos >= 7) { if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) { tip = "-> MIFARE Plus X 2K or 4K"; } else if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) { tip = "-> MIFARE Plus S 2K or 4K"; } } PrintAndLog(" - HB : %s%s", sprint_hex(card.ats + pos, card.ats[0] - pos), tip); if (card.ats[pos] == 0xC1) { PrintAndLog(" c1 -> Mifare or (multiple) virtual cards of various type"); PrintAndLog(" %02x -> Length is %d bytes", card.ats[pos + 1], card.ats[pos + 1]); switch (card.ats[pos + 2] & 0xf0) { case 0x10: PrintAndLog(" 1x -> MIFARE DESFire"); break; case 0x20: PrintAndLog(" 2x -> MIFARE Plus"); break; } switch (card.ats[pos + 2] & 0x0f) { case 0x00: PrintAndLog(" x0 -> <1 kByte"); break; case 0x01: PrintAndLog(" x0 -> 1 kByte"); break; case 0x02: PrintAndLog(" x0 -> 2 kByte"); break; case 0x03: PrintAndLog(" x0 -> 4 kByte"); break; case 0x04: PrintAndLog(" x0 -> 8 kByte"); break; } switch (card.ats[pos + 3] & 0xf0) { case 0x00: PrintAndLog(" 0x -> Engineering sample"); break; case 0x20: PrintAndLog(" 2x -> Released"); break; } switch (card.ats[pos + 3] & 0x0f) { case 0x00: PrintAndLog(" x0 -> Generation 1"); break; case 0x01: PrintAndLog(" x1 -> Generation 2"); break; case 0x02: PrintAndLog(" x2 -> Generation 3"); break; } switch (card.ats[pos + 4] & 0x0f) { case 0x00: PrintAndLog(" x0 -> Only VCSL supported"); break; case 0x01: PrintAndLog(" x1 -> VCS, VCSL, and SVC supported"); break; case 0x0E: PrintAndLog(" xE -> no VCS command supported"); break; } } } } else {
int CmdHF14AMfDESAuth(const char *Cmd){ uint8_t blockNo = 0; //keyNo=0; uint32_t cuid=0; uint8_t reply[16]; //DES_cblock r1_b1; uint8_t b1[8]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; uint8_t b2[8]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; DES_cblock nr, b0, r1, r0; uint8_t key[8]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; //DES_cblock iv={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; DES_key_schedule ks1; DES_cblock key1; if (strlen(Cmd)<1) { PrintAndLog("Usage: hf desfire des-auth k <key number>"); PrintAndLog(" sample: hf desfire des-auth k 0"); return 0; } //Change key to user defined one memcpy(key1,key,8); //memcpy(key2,key+8,8); DES_set_key((DES_cblock *)key1,&ks1); //DES_set_key((DES_cblock *)key2,&ks2); //Auth1 UsbCommand c = {CMD_MIFARE_DES_AUTH1, {blockNo}}; SendCommand(&c); UsbCommand resp; if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { uint8_t isOK = resp.arg[0] & 0xff; cuid = resp.arg[1]; uint8_t * data= resp.d.asBytes; if (isOK){ PrintAndLog("enc(nc)/b0:%s", sprint_hex(data+2,8)); memcpy(b0,data+2,8); } } else { PrintAndLog("Command execute timeout"); } //Do crypto magic DES_random_key(&nr); //b1=dec(nr) //r0=dec(b0) DES_ecb_encrypt(&nr,&b1,&ks1,0); DES_ecb_encrypt(&b0,&r0,&ks1,0); //PrintAndLog("b1:%s",sprint_hex(b1, 8)); PrintAndLog("r0:%s",sprint_hex(r0, 8)); //r1=rol(r0) memcpy(r1,r0,8); rol(r1,8); PrintAndLog("r1:%s",sprint_hex(r1, 8)); for(int i=0;i<8;i++){ b2[i]=(r1[i] ^ b1[i]); } DES_ecb_encrypt(&b2,&b2,&ks1,0); //PrintAndLog("b1:%s",sprint_hex(b1, 8)); PrintAndLog("b2:%s",sprint_hex(b2, 8)); //Auth2 UsbCommand d = {CMD_MIFARE_DES_AUTH2, {cuid}}; memcpy(reply,b1,8); memcpy(reply+8,b2,8); memcpy(d.d.asBytes,reply, 16); SendCommand(&d); UsbCommand respb; if (WaitForResponseTimeout(CMD_ACK,&respb,1500)) { uint8_t isOK = respb.arg[0] & 0xff; uint8_t * data2= respb.d.asBytes; if (isOK){ PrintAndLog("b3:%s", sprint_hex(data2+2, 8)); } } else { PrintAndLog("Command execute timeout"); } return 1; }
int ManchesterConvertFrom1(const int * data, const size_t len, uint8_t * dataout,int dataoutlen, int clock, int startIndex){ int i,j, bitindex, lc, tolerance, warnings; warnings = 0; int upperlimit = len*2/clock+8; i = startIndex; j = 0; tolerance = clock/4; uint8_t decodedArr[len]; /* Detect duration between 2 successive transitions */ for (bitindex = 1; i < len; i++) { if (data[i-1] != data[i]) { lc = i - startIndex; startIndex = i; // Error check: if bitindex becomes too large, we do not // have a Manchester encoded bitstream or the clock is really wrong! if (bitindex > upperlimit ) { PrintAndLog("Error: the clock you gave is probably wrong, aborting."); return 0; } // Then switch depending on lc length: // Tolerance is 1/4 of clock rate (arbitrary) if (abs((lc-clock)/2) < tolerance) { // Short pulse : either "1" or "0" decodedArr[bitindex++] = data[i-1]; } else if (abs(lc-clock) < tolerance) { // Long pulse: either "11" or "00" decodedArr[bitindex++] = data[i-1]; decodedArr[bitindex++] = data[i-1]; } else { ++warnings; PrintAndLog("Warning: Manchester decode error for pulse width detection."); if (warnings > 10) { PrintAndLog("Error: too many detection errors, aborting."); return 0; } } } } /* * We have a decodedArr of "01" ("1") or "10" ("0") * parse it into final decoded dataout */ for (i = 0; i < bitindex; i += 2) { if ((decodedArr[i] == 0) && (decodedArr[i+1] == 1)) { dataout[j++] = 1; } else if ((decodedArr[i] == 1) && (decodedArr[i+1] == 0)) { dataout[j++] = 0; } else { i++; warnings++; PrintAndLog("Unsynchronized, resync..."); PrintAndLog("(too many of those messages mean the stream is not Manchester encoded)"); if (warnings > 10) { PrintAndLog("Error: too many decode errors, aborting."); return 0; } } } PrintAndLog("%s", sprint_hex(dataout, j)); return j; }
void AddLogHex(char *fileName, char *extData, const uint8_t * data, const size_t len){ AddLogLine(fileName, extData, sprint_hex(data, len)); }
//EV1 // Reader 2 Card : 02AA, key (1 byte), CRC1 CRC2 ; auth // Card 2 Reader : 02AF, 16 Bytes(b0), CRC1 CRC2 // Reader 2 Card : 03AF, 16 Bytes(b1),16Bytes(b2) CRC1 CRC2 // Card 2 Reader : 0300, 16 bytes(b3), CRC1 CRC2 ; success int CmdHF14AMfAESAuth(const char *Cmd){ uint8_t blockNo = 0; //keyNo=0; uint32_t cuid=0; uint8_t reply[32]; //DES_cblock r1_b1; //unsigned char * b1, b2, nr, b0, r0, r1; uint8_t b1[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; uint8_t b2[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; uint8_t nr[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; uint8_t b0[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; uint8_t r0[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; uint8_t r1[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; // uint8_t key[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; uint8_t iv[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; AES_KEY key_e; AES_KEY key_d; if (strlen(Cmd)<1) { PrintAndLog("Usage: hf desfire aes-auth k <key number>"); PrintAndLog(" sample: hf desfire aes-auth k 0"); return 0; } //Change key to user defined one // // int private_AES_set_encrypt_key(const unsigned char *userKey, const int bits,AES_KEY *key); //int private_AES_set_decrypt_key(const unsigned char *userKey, const int bits,AES_KEY *key); // //memcpy(key1,key,16); //memcpy(key2,key+8,8); AES_set_encrypt_key(key,128,&key_e); AES_set_decrypt_key(key,128,&key_d); //Auth1 UsbCommand c = {CMD_MIFARE_DES_AUTH1, {blockNo}}; SendCommand(&c); UsbCommand resp; if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { uint8_t isOK = resp.arg[0] & 0xff; cuid = resp.arg[1]; uint8_t * data= resp.d.asBytes; if (isOK){ PrintAndLog("enc(nc)/b0:%s", sprint_hex(data+2,16)); memcpy(b0,data+2,16); } } else { PrintAndLog("Command execute timeout"); } // // void AES_cbc_encrypt(const unsigned char *in, unsigned char *out, //size_t length, const AES_KEY *key, //unsigned char *ivec, const int enc); //Do crypto magic //DES_random_key(&nr); //b1=dec(nr) //r0=dec(b0) //AES_cbc_encrypt(&nr,&b1,16,&key,0); AES_cbc_encrypt(&b0,&r0,16,&key_d,iv,0); //PrintAndLog("b1:%s",sprint_hex(b1, 8)); PrintAndLog("r0:%s",sprint_hex(r0, 16)); //r1=rol(r0) memcpy(r1,r0,16); rol(r1,8); PrintAndLog("r1:%s",sprint_hex(r1, 16)); for(int i=0;i<16;i++){ b1[i]=(nr[i] ^ b0[i]); b2[i]=(r1[i] ^ b1[i]); } PrintAndLog("nr:%s",sprint_hex(nr, 16)); AES_cbc_encrypt(&b1,&b1,16,&key_e,iv,1); AES_cbc_encrypt(&b2,&b2,16,&key_e,iv,1); PrintAndLog("b1:%s",sprint_hex(b1, 16)); PrintAndLog("b2:%s",sprint_hex(b2, 16)); //Auth2 UsbCommand d = {CMD_MIFARE_DES_AUTH2, {cuid}}; memcpy(reply,b1,16); memcpy(reply+16,b2,16); memcpy(d.d.asBytes,reply, 32); SendCommand(&d); UsbCommand respb; if (WaitForResponseTimeout(CMD_ACK,&respb,1500)) { uint8_t isOK = respb.arg[0] & 0xff; uint8_t * data2= respb.d.asBytes; if (isOK){ PrintAndLog("b3:%s", sprint_hex(data2+2, 16)); } } else { PrintAndLog("Command execute timeout"); } return 1; }
int CmdHF15Raw(const char *Cmd) { char cmdp = param_getchar(Cmd, 0); if (strlen(Cmd)<3 || cmdp == 'h' || cmdp == 'H') return usage_15_raw(); UsbCommand resp; UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv? int reply = 1, fast = 1, i = 0; bool crc = false; char buf[5] = ""; uint8_t data[100]; uint32_t datalen = 0, temp; // strip while (*Cmd==' ' || *Cmd=='\t') Cmd++; while (Cmd[i]!='\0') { if (Cmd[i]==' ' || Cmd[i]=='\t') { i++; continue; } if (Cmd[i]=='-') { switch (Cmd[i+1]) { case 'r': case 'R': reply = 0; break; case '2': fast = 0; break; case 'c': case 'C': crc = true; break; default: PrintAndLogEx(WARNING, "Invalid option"); return 0; } i+=2; continue; } if ((Cmd[i]>='0' && Cmd[i]<='9') || (Cmd[i]>='a' && Cmd[i]<='f') || (Cmd[i]>='A' && Cmd[i]<='F') ) { buf[strlen(buf)+1] = 0; buf[strlen(buf)] = Cmd[i]; i++; if (strlen(buf) >= 2) { sscanf(buf, "%x", &temp); data[datalen] = (uint8_t)(temp & 0xff); datalen++; *buf = 0; } continue; } PrintAndLogEx(WARNING, "Invalid char on input"); return 0; } if (crc) { AddCrc(data, datalen); datalen += 2; } c.arg[0] = datalen; c.arg[1] = fast; c.arg[2] = reply; memcpy(c.d.asBytes, data, datalen); clearCommandBuffer(); SendCommand(&c); if (reply) { if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { uint8_t len = resp.arg[0]; PrintAndLogEx(NORMAL, "received %i octets", len); PrintAndLogEx(NORMAL, "%s", sprint_hex(resp.d.asBytes, len) ); } else { PrintAndLogEx(WARNING, "timeout while waiting for reply."); } } return 0; }
int CmdFdxDemod(const char *Cmd){ //Differential Biphase / di-phase (inverted biphase) //get binary from ask wave if (!ASKbiphaseDemod("0 32 1 0", false)) { if (g_debugMode) PrintAndLog("DEBUG: Error - FDX-B ASKbiphaseDemod failed"); return 0; } size_t size = DemodBufferLen; int preambleIndex = FDXBdemodBI(DemodBuffer, &size); if (preambleIndex < 0){ if (g_debugMode){ if (preambleIndex == -1) PrintAndLog("DEBUG: Error - FDX-B too few bits found"); else if (preambleIndex == -2) PrintAndLog("DEBUG: Error - FDX-B preamble not found"); else if (preambleIndex == -3) PrintAndLog("DEBUG: Error - FDX-B Size not correct: %d", size); else PrintAndLog("DEBUG: Error - FDX-B ans: %d", preambleIndex); } return 0; } // set and leave DemodBuffer intact setDemodBuf(DemodBuffer, 128, preambleIndex); setClockGrid(g_DemodClock, g_DemodStartIdx + (preambleIndex*g_DemodClock)); uint8_t bits_no_spacer[117]; memcpy(bits_no_spacer, DemodBuffer + 11, 117); // remove marker bits (1's every 9th digit after preamble) (pType = 2) size = removeParity(bits_no_spacer, 0, 9, 2, 117); if ( size != 104 ) { if (g_debugMode) PrintAndLog("DEBUG: Error removeParity:: %d", size); return 0; } //got a good demod uint64_t NationalCode = ((uint64_t)(bytebits_to_byteLSBF(bits_no_spacer+32,6)) << 32) | bytebits_to_byteLSBF(bits_no_spacer,32); uint32_t countryCode = bytebits_to_byteLSBF(bits_no_spacer+38,10); uint8_t dataBlockBit = bits_no_spacer[48]; uint32_t reservedCode = bytebits_to_byteLSBF(bits_no_spacer+49,14); uint8_t animalBit = bits_no_spacer[63]; uint32_t crc16 = bytebits_to_byteLSBF(bits_no_spacer+64,16); uint32_t extended = bytebits_to_byteLSBF(bits_no_spacer+80,24); uint64_t rawid = ((uint64_t)bytebits_to_byte(bits_no_spacer,32)<<32) | bytebits_to_byte(bits_no_spacer+32,32); uint8_t raw[8]; num_to_bytes(rawid, 8, raw); if (g_debugMode) { PrintAndLog("DEBUG: bits_no_spacer:\n%s",sprint_bin_break(bits_no_spacer,size,16)); PrintAndLog("DEBUG: Start marker %d; Size %d", preambleIndex, size); PrintAndLog("DEBUG: Raw ID Hex: %s", sprint_hex(raw,8)); } uint16_t calcCrc = crc16_ccitt_kermit(raw, 8); PrintAndLog("\nFDX-B / ISO 11784/5 Animal Tag ID Found:"); PrintAndLog("Animal ID: %04u-%012" PRIu64, countryCode, NationalCode); PrintAndLog("National Code: %012" PRIu64, NationalCode); PrintAndLog("CountryCode: %04u", countryCode); PrintAndLog("Reserved Code: %u", reservedCode); PrintAndLog("Animal Tag: %s", animalBit ? "True" : "False"); PrintAndLog("Has Extended: %s [0x%X]", dataBlockBit ? "True" : "False", extended); PrintAndLog("CRC: 0x%04X - 0x%04X - [%s]\n", crc16, calcCrc, (calcCrc == crc16) ? "Passed" : "Failed"); // set block 0 for later //g_DemodConfig = T55x7_MODULATION_DIPHASE | T55x7_BITRATE_RF_32 | 4 << T55x7_MAXBLOCK_SHIFT; return 1; }
// Reads all memory pages // need to write to file int CmdHF15Dump(const char*Cmd) { uint8_t fileNameLen = 0; char filename[FILE_PATH_SIZE] = {0}; char * fptr = filename; bool errors = false; uint8_t cmdp = 0; uint8_t uid[8] = {0,0,0,0,0,0,0,0}; while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch(param_getchar(Cmd, cmdp)) { case 'h': case 'H': return usage_15_dump(); case 'f': case 'F': fileNameLen = param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE); cmdp += 2; break; default: PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); errors = true; break; } } //Validations if (errors) return usage_15_dump(); if (fileNameLen < 1) { PrintAndLogEx(INFO, "Using UID as filename"); if (!getUID(uid)) { PrintAndLogEx(WARNING, "No tag found."); return 1; } fptr += sprintf(fptr, "hf-15-"); FillFileNameByUID(fptr,uid,"-dump",sizeof(uid)); } // detect blocksize from card :) PrintAndLogEx(NORMAL, "Reading memory from tag UID %s", sprintUID(NULL, uid)); int blocknum = 0; uint8_t *recv = NULL; // memory. t15memory mem[256]; uint8_t data[256*4] = {0}; memset(data, 0, sizeof(data)); UsbCommand resp; UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv? uint8_t *req = c.d.asBytes; req[0] = ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS; req[1] = ISO15_CMD_READ; // copy uid to read command memcpy(req+2, uid, sizeof(uid)); for (int retry = 0; retry < 5; retry++) { req[10] = blocknum; AddCrc(req, 11); c.arg[0] = 13; clearCommandBuffer(); SendCommand(&c); if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { uint8_t len = resp.arg[0]; if ( len < 2 ) { PrintAndLogEx(FAILED, "iso15693 card select failed"); continue; } recv = resp.d.asBytes; if ( !CheckCrc(recv, len) ) { PrintAndLogEx(FAILED, "crc fail"); continue; } if (recv[0] & ISO15_RES_ERROR) { PrintAndLogEx(FAILED, "Tag returned Error %i: %s", recv[1], TagErrorStr(recv[1]) ); break; } mem[blocknum].lock = resp.d.asBytes[0]; memcpy(mem[blocknum].block, resp.d.asBytes + 1, 4); memcpy(data + (blocknum * 4), resp.d.asBytes + 1, 4); retry = 0; blocknum++; printf("."); fflush(stdout); } } PrintAndLogEx(NORMAL, "\n"); PrintAndLogEx(NORMAL, "block# | data |lck| ascii"); PrintAndLogEx(NORMAL, "---------+--------------+---+----------"); for (int i = 0; i < blocknum; i++) { PrintAndLogEx(NORMAL, "%3d/0x%02X | %s | %d | %s", i, i, sprint_hex(mem[i].block, 4 ), mem[i].lock, sprint_ascii(mem[i].block, 4) ); } PrintAndLogEx(NORMAL, "\n"); size_t datalen = blocknum * 4; saveFileEML(filename, "eml", data, datalen, 4); saveFile(filename, "bin", data, datalen); return 0; }
/* * Output BigBuf and deobfuscate LEGIC RF tag data. * This is based on information given in the talk held * by Henryk Ploetz and Karsten Nohl at 26c3 */ int CmdLegicDecode(const char *Cmd) { // Index for the bytearray. int i = 0; int k = 0, segmentNum; int segment_len = 0; int segment_flag = 0; uint8_t stamp_len = 0; int crc = 0; int wrp = 0; int wrc = 0; uint8_t data_buf[1024]; // receiver buffer, should be 1024.. char token_type[4]; // download EML memory, where the "legic read" command puts the data. GetEMLFromBigBuf(data_buf, sizeof(data_buf), 0); if ( !WaitForResponseTimeout(CMD_ACK, NULL, 2000)){ PrintAndLog("Command execute timeout"); return 1; } // Output CDF System area (9 bytes) plus remaining header area (12 bytes) crc = data_buf[4]; uint32_t calc_crc = CRC8Legic(data_buf, 4); PrintAndLog("\nCDF: System Area"); PrintAndLog("------------------------------------------------------"); PrintAndLog("MCD: %02x, MSN: %02x %02x %02x, MCC: %02x %s", data_buf[0], data_buf[1], data_buf[2], data_buf[3], data_buf[4], (calc_crc == crc) ? "OK":"Fail" ); switch (data_buf[5] & 0x7f) { case 0x00 ... 0x2f: strncpy(token_type, "IAM",sizeof(token_type)); break; case 0x30 ... 0x6f: strncpy(token_type, "SAM",sizeof(token_type)); break; case 0x70 ... 0x7f: strncpy(token_type, "GAM",sizeof(token_type)); break; default: strncpy(token_type, "???",sizeof(token_type)); break; } stamp_len = 0xfc - data_buf[6]; PrintAndLog("DCF: %02x %02x, Token Type=%s (OLE=%01u), Stamp len=%02u", data_buf[5], data_buf[6], token_type, (data_buf[5]&0x80)>>7, stamp_len ); PrintAndLog("WRP=%02u, WRC=%01u, RD=%01u, raw=%02x, SSC=%02x", data_buf[7]&0x0f, (data_buf[7]&0x70)>>4, (data_buf[7]&0x80)>>7, data_buf[7], data_buf[8] ); PrintAndLog("Remaining Header Area"); PrintAndLog("%s", sprint_hex(data_buf+9, 13)); uint8_t segCrcBytes[8] = {0x00}; uint32_t segCalcCRC = 0; uint32_t segCRC = 0; // see if user area is xored or just zeros. int numOfZeros = 0; for (int index=22; index < 256; ++index){ if ( data_buf[index] == 0x00 ) ++numOfZeros; } // if possible zeros is less then 60%, lets assume data is xored // 256 - 22 (header) = 234 // 1024 - 22 (header) = 1002 int isXored = (numOfZeros*100/stamp_len) < 50; PrintAndLog("is data xored? %d ( %d %)", isXored, (numOfZeros*100/stamp_len)); print_hex_break( data_buf, 33, 16); return 0; PrintAndLog("\nADF: User Area"); PrintAndLog("------------------------------------------------------"); i = 22; // 64 potential segements // how to detect there is no segments?!? for ( segmentNum=0; segmentNum<64; segmentNum++ ) { segment_len = ((data_buf[i+1]^crc)&0x0f) * 256 + (data_buf[i]^crc); segment_flag = ((data_buf[i+1]^crc)&0xf0)>>4; wrp = (data_buf[i+2]^crc); wrc = ((data_buf[i+3]^crc)&0x70)>>4; bool hasWRC = (wrc > 0); bool hasWRP = (wrp > wrc); int wrp_len = (wrp - wrc); int remain_seg_payload_len = (segment_len - wrp - 5); // validate segment-crc segCrcBytes[0]=data_buf[0]; //uid0 segCrcBytes[1]=data_buf[1]; //uid1 segCrcBytes[2]=data_buf[2]; //uid2 segCrcBytes[3]=data_buf[3]; //uid3 segCrcBytes[4]=(data_buf[i]^crc); //hdr0 segCrcBytes[5]=(data_buf[i+1]^crc); //hdr1 segCrcBytes[6]=(data_buf[i+2]^crc); //hdr2 segCrcBytes[7]=(data_buf[i+3]^crc); //hdr3 segCalcCRC = CRC8Legic(segCrcBytes, 8); segCRC = data_buf[i+4]^crc; PrintAndLog("Segment %02u \nraw header | 0x%02X 0x%02X 0x%02X 0x%02X \nSegment len: %u, Flag: 0x%X (valid:%01u, last:%01u), WRP: %02u, WRC: %02u, RD: %01u, CRC: 0x%02X (%s)", segmentNum, data_buf[i]^crc, data_buf[i+1]^crc, data_buf[i+2]^crc, data_buf[i+3]^crc, segment_len, segment_flag, (segment_flag & 0x4) >> 2, (segment_flag & 0x8) >> 3, wrp, wrc, ((data_buf[i+3]^crc) & 0x80) >> 7, segCRC, ( segCRC == segCalcCRC ) ? "OK" : "fail" ); i += 5; if ( hasWRC ) { PrintAndLog("WRC protected area: (I %d | K %d| WRC %d)", i, k, wrc); PrintAndLog("\nrow | data"); PrintAndLog("-----+------------------------------------------------"); // de-xor? if not zero, assume it needs xoring. if ( isXored) { for ( k=i; k < wrc; ++k) data_buf[k] ^= crc; } print_hex_break( data_buf+i, wrc, 16); i += wrc; } if ( hasWRP ) { PrintAndLog("Remaining write protected area: (I %d | K %d | WRC %d | WRP %d WRP_LEN %d)",i, k, wrc, wrp, wrp_len); PrintAndLog("\nrow | data"); PrintAndLog("-----+------------------------------------------------"); if (isXored) { for (k=i; k < wrp_len; ++k) data_buf[k] ^= crc; } print_hex_break( data_buf+i, wrp_len, 16); i += wrp_len; // does this one work? if( wrp_len == 8 ) PrintAndLog("Card ID: %2X%02X%02X", data_buf[i-4]^crc, data_buf[i-3]^crc, data_buf[i-2]^crc); } PrintAndLog("Remaining segment payload: (I %d | K %d | Remain LEN %d)", i, k, remain_seg_payload_len); PrintAndLog("\nrow | data"); PrintAndLog("-----+------------------------------------------------"); if ( isXored ) { for ( k=i; k < remain_seg_payload_len; ++k) data_buf[k] ^= crc; } print_hex_break( data_buf+i, remain_seg_payload_len, 16); i += remain_seg_payload_len; PrintAndLog("-----+------------------------------------------------\n"); // end with last segment if (segment_flag & 0x8) return 0; } // end for loop return 0; }
/** * Commandline handling: HF15 CMD SYSINFO * get system information from tag/VICC */ int CmdHF15Info(const char *Cmd) { char cmdp = param_getchar(Cmd, 0); if (strlen(Cmd)<1 || cmdp == 'h' || cmdp == 'H') return usage_15_info(); UsbCommand resp; uint8_t *recv; UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv? uint8_t *req = c.d.asBytes; char cmdbuf[100]; char *cmd = cmdbuf; memset(cmdbuf, 0, sizeof(cmdbuf)); strncpy(cmd, Cmd, 99); if ( !prepareHF15Cmd(&cmd, &c, ISO15_CMD_SYSINFO) ) return 0; AddCrc(req, c.arg[0]); c.arg[0] += 2; //PrintAndLogEx(NORMAL, "cmd %s", sprint_hex(c.d.asBytes, reqlen) ); clearCommandBuffer(); SendCommand(&c); if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { PrintAndLogEx(NORMAL, "iso15693 card select failed"); return 1; } uint32_t status = resp.arg[0]; if ( status < 2 ) { PrintAndLogEx(NORMAL, "iso15693 card doesn't answer to systeminfo command"); return 1; } recv = resp.d.asBytes; if ( recv[0] & ISO15_RES_ERROR ) { PrintAndLogEx(NORMAL, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); return 3; } PrintAndLogEx(NORMAL, " UID : %s", sprintUID(NULL, recv+2)); PrintAndLogEx(NORMAL, " TYPE : %s", getTagInfo_15(recv+2)); PrintAndLogEx(NORMAL, " SYSINFO : %s", sprint_hex(recv, status-2)); // DSFID if (recv[1] & 0x01) PrintAndLogEx(NORMAL, " - DSFID supported [0x%02X]", recv[10]); else PrintAndLogEx(NORMAL, " - DSFID not supported"); // AFI if (recv[1] & 0x02) PrintAndLogEx(NORMAL, " - AFI supported [0x%02X]", recv[11]); else PrintAndLogEx(NORMAL, " - AFI not supported"); // IC reference if (recv[1] & 0x08) PrintAndLogEx(NORMAL, " - IC reference supported [0x%02X]", recv[14]); else PrintAndLogEx(NORMAL, " - IC reference not supported"); // memory if (recv[1] & 0x04) { PrintAndLogEx(NORMAL, " - Tag provides info on memory layout (vendor dependent)"); uint8_t blocks = recv[12]+1; uint8_t size = (recv[13] & 0x1F); PrintAndLogEx(NORMAL, " %u (or %u) bytes/blocks x %u blocks", size+1, size, blocks ); } else { PrintAndLogEx(NORMAL, " - Tag does not provide information on memory layout"); } PrintAndLogEx(NORMAL, "\n"); return 0; }
int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) { uint8_t data[64]; if (traceState == TRACE_ERROR) return 1; if (len > 64) { traceState = TRACE_ERROR; return 1; } memcpy(data, data_src, len); if ((traceCrypto1) && ((traceState == TRACE_IDLE) || (traceState > TRACE_AUTH_OK))) { mf_crypto1_decrypt(traceCrypto1, data, len, 0); PrintAndLog("dec> %s", sprint_hex(data, len)); AddLogHex(logHexFileName, "dec> ", data, len); } switch (traceState) { case TRACE_IDLE: // check packet crc16! if ((len >= 4) && (!CheckCrc14443(CRC_14443_A, data, len))) { PrintAndLog("dec> CRC ERROR!!!"); AddLogLine(logHexFileName, "dec> ", "CRC ERROR!!!"); traceState = TRACE_ERROR; // do not decrypt the next commands return 1; } // AUTHENTICATION if ((len == 4) && ((data[0] == 0x60) || (data[0] == 0x61))) { traceState = TRACE_AUTH1; traceCurBlock = data[1]; traceCurKey = data[0] == 60 ? 1:0; return 0; } // READ if ((len ==4) && ((data[0] == 0x30))) { traceState = TRACE_READ_DATA; traceCurBlock = data[1]; return 0; } // WRITE if ((len ==4) && ((data[0] == 0xA0))) { traceState = TRACE_WRITE_OK; traceCurBlock = data[1]; return 0; } // HALT if ((len ==4) && ((data[0] == 0x50) && (data[1] == 0x00))) { traceState = TRACE_ERROR; // do not decrypt the next commands return 0; } return 0; break; case TRACE_READ_DATA: if (len == 18) { traceState = TRACE_IDLE; if (isBlockTrailer(traceCurBlock)) { memcpy(traceCard + traceCurBlock * 16 + 6, data + 6, 4); } else { memcpy(traceCard + traceCurBlock * 16, data, 16); } if (wantSaveToEmlFile) saveTraceCard(); return 0; } else { traceState = TRACE_ERROR; return 1; } break; case TRACE_WRITE_OK: if ((len == 1) && (data[0] == 0x0a)) { traceState = TRACE_WRITE_DATA; return 0; } else { traceState = TRACE_ERROR; return 1; } break; case TRACE_WRITE_DATA: if (len == 18) { traceState = TRACE_IDLE; memcpy(traceCard + traceCurBlock * 16, data, 16); if (wantSaveToEmlFile) saveTraceCard(); return 0; } else { traceState = TRACE_ERROR; return 1; } break; case TRACE_AUTH1: if (len == 4) { traceState = TRACE_AUTH2; nt = bytes_to_num(data, 4); return 0; } else { traceState = TRACE_ERROR; return 1; } break; case TRACE_AUTH2: if (len == 8) { traceState = TRACE_AUTH_OK; nr_enc = bytes_to_num(data, 4); ar_enc = bytes_to_num(data + 4, 4); return 0; } else { traceState = TRACE_ERROR; return 1; } break; case TRACE_AUTH_OK: if (len ==4) { traceState = TRACE_IDLE; at_enc = bytes_to_num(data, 4); // decode key here) ks2 = ar_enc ^ prng_successor(nt, 64); ks3 = at_enc ^ prng_successor(nt, 96); revstate = lfsr_recovery64(ks2, ks3); lfsr_rollback_word(revstate, 0, 0); lfsr_rollback_word(revstate, 0, 0); lfsr_rollback_word(revstate, nr_enc, 1); lfsr_rollback_word(revstate, uid ^ nt, 0); crypto1_get_lfsr(revstate, &key); printf("Key: %012"llx"\n",key); AddLogUint64(logHexFileName, "key: ", key); int blockShift = ((traceCurBlock & 0xFC) + 3) * 16; if (isBlockEmpty((traceCurBlock & 0xFC) + 3)) memcpy(traceCard + blockShift + 6, trailerAccessBytes, 4); if (traceCurKey) { num_to_bytes(key, 6, traceCard + blockShift + 10); } else { num_to_bytes(key, 6, traceCard + blockShift); } if (wantSaveToEmlFile) saveTraceCard(); if (traceCrypto1) { crypto1_destroy(traceCrypto1); } // set cryptosystem state traceCrypto1 = lfsr_recovery64(ks2, ks3); // nt = crypto1_word(traceCrypto1, nt ^ uid, 1) ^ nt; /* traceCrypto1 = crypto1_create(key); // key in lfsr crypto1_word(traceCrypto1, nt ^ uid, 0); crypto1_word(traceCrypto1, ar, 1); crypto1_word(traceCrypto1, 0, 0); crypto1_word(traceCrypto1, 0, 0);*/ return 0; } else { traceState = TRACE_ERROR; return 1; } break; default: traceState = TRACE_ERROR; return 1; } return 0; }
int NFC_afficher_UID (char *ATQA, char *UID, char *SAQ, char * ATS) //! Attention à la taille des tableaux de caractères ! { nfc_device *pnd; nfc_target nt; nfc_context *context; nfc_init(&context); if (context == NULL) { sprintf(message_erreur,"ERREUR : Impossible d'utiliser LIBNFC !"); return EXIT_FAILURE; //! ERREUR : Impossible d'utiliser LIBNFC ! } pnd = nfc_open(context, NULL); if (pnd == NULL) { sprintf(message_erreur,"Error opening NFC reader !"); return EXIT_FAILURE; //! ERREUR : Aucun périphérique détecté ! } if (nfc_initiator_init(pnd) < 0) { nfc_perror(pnd, "nfc_initiator_init"); nfc_strerror_r(pnd, message_erreur, TAILLE_MESSAGE_ERREUR); return EXIT_FAILURE; //! ERREUR - Sortie de la fonction } #ifdef DEBUG_PRINTF fprintf(stderr,"Lecteur NFC : %s\n", nfc_device_get_name(pnd)); //! Identifiant du lecteur NFC #endif const nfc_modulation nmMifare = { .nmt = NMT_ISO14443A, .nbr = NBR_106, }; if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) > 0) { #ifdef DEBUG_PRINTF fprintf(stderr,"L'étiquette (NFC) ISO14443A suivante a été trouvée :\n\n"); fprintf(stderr," ATQA (SENS_RES): "); fprintf(stderr,"\033[%sm","31"); #endif sprint_hex(nt.nti.nai.abtAtqa,2,ATQA); //! Récupération du ATQA #ifdef DEBUG_PRINTF fprintf(stderr,"\033[%sm","0"); fprintf(stderr,"\n UID (NFCID%c): ", (nt.nti.nai.abtUid[0] == 0x08 ? '3' : '1')); fprintf(stderr,"\033[%sm","31"); #endif sprint_hex(nt.nti.nai.abtUid,nt.nti.nai.szUidLen,UID); //! Récupération du UID #ifdef DEBUG_PRINTF fprintf(stderr,"\033[%sm","0"); fprintf(stderr,"\n SAK (SEL_RES): "); fprintf(stderr,"\033[%sm","31"); #endif sprint_hex(&nt.nti.nai.btSak,1,SAQ); //! Récupération du SAQ #ifdef DEBUG_PRINTF fprintf(stderr,"\033[%sm","0"); #endif if (nt.nti.nai.szAtsLen) { #ifdef DEBUG_PRINTF fprintf(stderr,"\n ATS (ATR): "); fprintf(stderr,"\033[%sm","31"); #endif sprint_hex(nt.nti.nai.abtAts,nt.nti.nai.szAtsLen,ATS); //! Récupération du ATS #ifdef DEBUG_PRINTF fprintf(stderr,"\033[%sm","0"); #endif } #ifdef DEBUG_PRINTF fprintf(stderr,"\n"); #endif } nfc_close(pnd); //! On libère le périphérique NFC nfc_exit(context); return EXIT_SUCCESS; //! Succès ! }