X-Git-Url: http://cvs.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/fecd8202a5ad638db4c1ba088842390e78ef52db..2e9d4b3ff492826eeaa7c5eefb905fcff3eb003c:/client/cmdhficlass.c diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index e68fdc4f..19ec57d2 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -1,7 +1,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 2010 iZsh , Hagen Fritsch // Copyright (C) 2011 Gerhard de Koning Gans -// Copyright (C) 2014 Midnitesnake & Andy Davies +// Copyright (C) 2014 Midnitesnake & Andy Davies & Martin Holst Swende // // 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 @@ -13,6 +13,7 @@ #include #include #include +#include #include "iso14443crc.h" // Can also be used for iClass, using 0xE012 as CRC-type #include "data.h" //#include "proxusb.h" @@ -22,147 +23,190 @@ #include "cmdhficlass.h" #include "common.h" #include "util.h" +#include "cmdmain.h" #include "loclass/des.h" #include "loclass/cipherutils.h" #include "loclass/cipher.h" #include "loclass/ikeys.h" +#include "loclass/elite_crack.h" +#include "loclass/fileutils.h" static int CmdHelp(const char *Cmd); -int CmdHFiClassList(const char *Cmd) +int xorbits_8(uint8_t val) { - uint8_t got[1920]; - GetFromBigBuf(got,sizeof(got),0); - - PrintAndLog("recorded activity:"); - PrintAndLog(" ETU :rssi: who bytes"); - PrintAndLog("---------+----+----+-----------"); - - int i = 0; - int prev = -1; - - for (;;) { - if(i >= 1900) { - break; - } - - bool isResponse; - int timestamp = *((uint32_t *)(got+i)); - if (timestamp & 0x80000000) { - timestamp &= 0x7fffffff; - isResponse = 1; - } else { - isResponse = 0; - } - - int metric = 0; - int parityBits = *((uint32_t *)(got+i+4)); - // 4 bytes of additional information... - // maximum of 32 additional parity bit information - // - // TODO: - // at each quarter bit period we can send power level (16 levels) - // or each half bit period in 256 levels. - - - int len = got[i+8]; - - if (len > 100) { - break; - } - if (i + len >= 1900) { - break; - } - - uint8_t *frame = (got+i+9); - - // Break and stick with current result if buffer was not completely full - if (frame[0] == 0x44 && frame[1] == 0x44 && frame[3] == 0x44) { break; } - - char line[1000] = ""; - int j; - for (j = 0; j < len; j++) { - int oddparity = 0x01; - int k; + uint8_t res = val ^ (val >> 1); //1st pass + res = res ^ (res >> 1); // 2nd pass + res = res ^ (res >> 2); // 3rd pass + res = res ^ (res >> 4); // 4th pass + return res & 1; +} - for (k=0;k<8;k++) { - oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01); - } +void explain(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) +{ - //if((parityBits >> (len - j - 1)) & 0x01) { - if (isResponse && (oddparity != ((parityBits >> (len - j - 1)) & 0x01))) { - sprintf(line+(j*4), "%02x! ", frame[j]); - } - else { - sprintf(line+(j*4), "%02x ", frame[j]); - } + switch(cmd[0]) + { + case 0x0a: snprintf(exp,size,"WUP"); break; + case 0x0f: snprintf(exp,size,"SOF"); break; + case 0x0c: snprintf(exp,size,"Read config"); break; + case 0x81: snprintf(exp,size,"SELECT"); break; + case 0x88: snprintf(exp,size,"Read E-purse (CC)"); break; + case 0x05: snprintf(exp,size,"Reader challenge"); break; + case 0x00: snprintf(exp,size,"End"); break; + default: snprintf(exp,size,"?"); break; } + return; +} - char *crc; - crc = ""; - if (len > 2) { - uint8_t b1, b2; - for (j = 0; j < (len - 1); j++) { - // gives problems... search for the reason.. - /*if(frame[j] == 0xAA) { - switch(frame[j+1]) { - case 0x01: - crc = "[1] Two drops close after each other"; - break; - case 0x02: - crc = "[2] Potential SOC with a drop in second half of bitperiod"; - break; - case 0x03: - crc = "[3] Segment Z after segment X is not possible"; - break; - case 0x04: - crc = "[4] Parity bit of a fully received byte was wrong"; - break; - default: - crc = "[?] Unknown error"; - break; - } - break; - }*/ - } - - if (strlen(crc)==0) { - if(!isResponse && len == 4) { - // Rough guess that this is a command from the reader - // For iClass the command byte is not part of the CRC - ComputeCrc14443(CRC_ICLASS, &frame[1], len-3, &b1, &b2); - } - else { - // For other data.. CRC might not be applicable (UPDATE commands etc.) - ComputeCrc14443(CRC_ICLASS, frame, len-2, &b1, &b2); +int CmdHFiClassList(const char *Cmd) +{ + bool ShowWaitCycles = false; + char param = param_getchar(Cmd, 0); + + if (param != 0) { + PrintAndLog("List data in trace buffer."); + PrintAndLog("Usage: hf iclass list"); + PrintAndLog("h - help"); + PrintAndLog("sample: hf iclass list"); + return 0; } - //printf("%1x %1x",(unsigned)b1,(unsigned)b2); - if (b1 != frame[len-2] || b2 != frame[len-1]) { - crc = (isResponse & (len < 8)) ? "" : " !crc"; - } else { - crc = ""; - } - } - } else { - crc = ""; // SHORT - } - - char metricString[100]; - if (isResponse) { - sprintf(metricString, "%3d", metric); - } else { - strcpy(metricString, " "); - } - PrintAndLog(" +%7d: %s: %s %s %s", - (prev < 0 ? 0 : (timestamp - prev)), - metricString, - (isResponse ? "TAG" : " "), line, crc); - - prev = timestamp; - i += (len + 9); - } - return 0; +// for the time being. Need better Bigbuf handling. +#define TRACE_SIZE 3000 + + uint8_t trace[TRACE_SIZE]; + GetFromBigBuf(trace, TRACE_SIZE, 0); + WaitForResponse(CMD_ACK, NULL); + + PrintAndLog("Recorded Activity"); + PrintAndLog(""); + PrintAndLog("Start = Start of Start Bit, End = End of last modulation. Src = Source of Transfer"); + PrintAndLog("All times are in carrier periods (1/13.56Mhz)"); + PrintAndLog(""); + PrintAndLog(" Start | End | Src | Data (! denotes parity error) | CRC | Explanation|"); + PrintAndLog("-----------|-----------|-----|-------------------------------------------------------------------------------------"); + + uint16_t tracepos = 0; + uint16_t duration; + uint16_t data_len; + uint16_t parity_len; + bool isResponse; + uint32_t timestamp; + uint32_t first_timestamp; + uint32_t EndOfTransmissionTimestamp; + char explanation[20] = {0}; + for (;;) { + + if(tracepos >= TRACE_SIZE) { + break; + } + + timestamp = *((uint32_t *)(trace + tracepos)); + if(tracepos == 0) { + first_timestamp = timestamp; + } + + // Break and stick with current result if buffer was not completely full + if (timestamp == 0x44444444) break; + + tracepos += 4; + duration = *((uint16_t *)(trace + tracepos)); + tracepos += 2; + data_len = *((uint16_t *)(trace + tracepos)); + tracepos += 2; + + if (data_len & 0x8000) { + data_len &= 0x7fff; + isResponse = true; + } else { + isResponse = false; + } + + parity_len = (data_len-1)/8 + 1; + + if (tracepos + data_len + parity_len >= TRACE_SIZE) { + break; + } + + uint8_t *frame = trace + tracepos; + tracepos += data_len; + uint8_t *parityBytes = trace + tracepos; + tracepos += parity_len; + + char line[16][110]; + for (int j = 0; j < data_len; j++) { + int oddparity = 0x01; + int k; + + for (k=0;k<8;k++) { + oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01); + } + + uint8_t parityBits = parityBytes[j>>3]; + if (isResponse && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) { + sprintf(line[j/16]+((j%16)*4), "%02x! ", frame[j]); + } else { + sprintf(line[j/16]+((j%16)*4), "%02x ", frame[j]); + } + + } + + char *crc = " "; + if (data_len > 2) { + uint8_t b1, b2; + if(!isResponse && data_len == 4 ) { + // Rough guess that this is a command from the reader + // For iClass the command byte is not part of the CRC + ComputeCrc14443(CRC_ICLASS, &frame[1], data_len-3, &b1, &b2); + if (b1 != frame[data_len-2] || b2 != frame[data_len-1]) { + crc = "!crc"; + } + } + else { + // For other data.. CRC might not be applicable (UPDATE commands etc.) + ComputeCrc14443(CRC_ICLASS, frame, data_len-2, &b1, &b2); + if (b1 != frame[data_len-2] || b2 != frame[data_len-1]) { + crc = "!crc"; + } + } + } + + EndOfTransmissionTimestamp = timestamp + duration; + explain(explanation,sizeof(explanation),frame,data_len); + int num_lines = (data_len - 1)/16 + 1; + for (int j = 0; j < num_lines; j++) { + if (j == 0) { + PrintAndLog(" %9d | %9d | %s | %-64s| %s| %s", + (timestamp - first_timestamp), + (EndOfTransmissionTimestamp - first_timestamp), + (isResponse ? "Tag" : "Rdr"), + line[j], + (j == num_lines-1)?crc:" ", + explanation); + } else { + PrintAndLog(" | | | %-64s| %s", + line[j], + (j == num_lines-1)?crc:" "); + } + } + + bool next_isResponse = *((uint16_t *)(trace + tracepos + 6)) & 0x8000; + + if (ShowWaitCycles && !isResponse && next_isResponse) { + uint32_t next_timestamp = *((uint32_t *)(trace + tracepos)); + if (next_timestamp != 0x44444444) { + PrintAndLog(" %9d | %9d | %s | fdt (Frame Delay Time): %d", + (EndOfTransmissionTimestamp - first_timestamp), + (next_timestamp - first_timestamp), + " ", + (next_timestamp - EndOfTransmissionTimestamp)); + } + } + + } + + return 0; } int CmdHFiClassSnoop(const char *Cmd) @@ -171,47 +215,150 @@ int CmdHFiClassSnoop(const char *Cmd) SendCommand(&c); return 0; } - +#define NUM_CSNS 15 int CmdHFiClassSim(const char *Cmd) { uint8_t simType = 0; uint8_t CSN[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - if (strlen(Cmd)<2) { - PrintAndLog("Usage: hf iclass sim "); + if (strlen(Cmd)<1) { + PrintAndLog("Usage: hf iclass sim [0 ] | x"); + PrintAndLog(" options"); + PrintAndLog(" 0 simulate the given CSN"); + PrintAndLog(" 1 simulate default CSN"); + PrintAndLog(" 2 iterate CSNs, gather MACs"); PrintAndLog(" sample: hf iclass sim 0 031FEC8AF7FF12E0"); + PrintAndLog(" sample: hf iclass sim 2"); return 0; } simType = param_get8(Cmd, 0); - if (param_gethex(Cmd, 1, CSN, 16)) { - PrintAndLog("A CSN should consist of 16 HEX symbols"); - return 1; - } - PrintAndLog("--simtype:%02x csn:%s", simType, sprint_hex(CSN, 8)); - UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType}}; - memcpy(c.d.asBytes, CSN, 8); - SendCommand(&c); + if(simType == 0) + { + if (param_gethex(Cmd, 1, CSN, 16)) { + PrintAndLog("A CSN should consist of 16 HEX symbols"); + return 1; + } + PrintAndLog("--simtype:%02x csn:%s", simType, sprint_hex(CSN, 8)); + + } + if(simType > 2) + { + PrintAndLog("Undefined simptype %d", simType); + return 1; + } + uint8_t numberOfCSNs=0; + + if(simType == 2) + { + UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType,NUM_CSNS}}; + UsbCommand resp = {0}; + + /*uint8_t csns[8 * NUM_CSNS] = { + 0x00,0x0B,0x0F,0xFF,0xF7,0xFF,0x12,0xE0 , + 0x00,0x13,0x94,0x7e,0x76,0xff,0x12,0xe0 , + 0x2a,0x99,0xac,0x79,0xec,0xff,0x12,0xe0 , + 0x17,0x12,0x01,0xfd,0xf7,0xff,0x12,0xe0 , + 0xcd,0x56,0x01,0x7c,0x6f,0xff,0x12,0xe0 , + 0x4b,0x5e,0x0b,0x72,0xef,0xff,0x12,0xe0 , + 0x00,0x73,0xd8,0x75,0x58,0xff,0x12,0xe0 , + 0x0c,0x90,0x32,0xf3,0x5d,0xff,0x12,0xe0 }; +*/ + + uint8_t csns[8*NUM_CSNS] = { + 0x00, 0x0B, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0, + 0x00, 0x04, 0x0E, 0x08, 0xF7, 0xFF, 0x12, 0xE0, + 0x00, 0x09, 0x0D, 0x05, 0xF7, 0xFF, 0x12, 0xE0, + 0x00, 0x0A, 0x0C, 0x06, 0xF7, 0xFF, 0x12, 0xE0, + 0x00, 0x0F, 0x0B, 0x03, 0xF7, 0xFF, 0x12, 0xE0, + 0x00, 0x08, 0x0A, 0x0C, 0xF7, 0xFF, 0x12, 0xE0, + 0x00, 0x0D, 0x09, 0x09, 0xF7, 0xFF, 0x12, 0xE0, + 0x00, 0x0E, 0x08, 0x0A, 0xF7, 0xFF, 0x12, 0xE0, + 0x00, 0x03, 0x07, 0x17, 0xF7, 0xFF, 0x12, 0xE0, + 0x00, 0x3C, 0x06, 0xE0, 0xF7, 0xFF, 0x12, 0xE0, + 0x00, 0x01, 0x05, 0x1D, 0xF7, 0xFF, 0x12, 0xE0, + 0x00, 0x02, 0x04, 0x1E, 0xF7, 0xFF, 0x12, 0xE0, + 0x00, 0x07, 0x03, 0x1B, 0xF7, 0xFF, 0x12, 0xE0, + 0x00, 0x00, 0x02, 0x24, 0xF7, 0xFF, 0x12, 0xE0, + 0x00, 0x05, 0x01, 0x21, 0xF7, 0xFF, 0x12, 0xE0 }; + + memcpy(c.d.asBytes, csns, 8*NUM_CSNS); + + SendCommand(&c); + if (!WaitForResponseTimeout(CMD_ACK, &resp, -1)) { + PrintAndLog("Command timed out"); + return 0; + } + + uint8_t num_mac_responses = resp.arg[1]; + PrintAndLog("Mac responses: %d MACs obtained (should be %d)", num_mac_responses,NUM_CSNS); + + size_t datalen = NUM_CSNS*24; + /* + * Now, time to dump to file. We'll use this format: + * <8-byte CSN><8-byte CC><4 byte NR><4 byte MAC>.... + * So, it should wind up as + * 8 * 24 bytes. + * + * The returndata from the pm3 is on the following format + * <4 byte NR><4 byte MAC> + * CC are all zeroes, CSN is the same as was sent in + **/ + void* dump = malloc(datalen); + memset(dump,0,datalen);//<-- Need zeroes for the CC-field + uint8_t i = 0; + for(i = 0 ; i < NUM_CSNS ; i++) + { + memcpy(dump+i*24, csns+i*8,8); //CSN + //8 zero bytes here... + //Then comes NR_MAC (eight bytes from the response) + memcpy(dump+i*24+16,resp.d.asBytes+i*8,8); + + } + /** Now, save to dumpfile **/ + saveFile("iclass_mac_attack", "bin", dump,datalen); + free(dump); + }else + { + UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType,numberOfCSNs}}; + memcpy(c.d.asBytes, CSN, 8); + SendCommand(&c); + } return 0; } int CmdHFiClassReader(const char *Cmd) { - uint8_t readerType = 0; - - if (strlen(Cmd)<1) { - PrintAndLog("Usage: hf iclass reader "); - PrintAndLog(" sample: hf iclass reader 0"); - return 0; - } - - readerType = param_get8(Cmd, 0); - PrintAndLog("--readertype:%02x", readerType); - - UsbCommand c = {CMD_READER_ICLASS, {readerType}}; + UsbCommand c = {CMD_READER_ICLASS, {0}}; SendCommand(&c); + UsbCommand resp; + while(!ukbhit()){ + if (WaitForResponseTimeout(CMD_ACK,&resp,4500)) { + uint8_t isOK = resp.arg[0] & 0xff; + uint8_t * data = resp.d.asBytes; + + PrintAndLog("isOk:%02x", isOK); + if( isOK == 0){ + //Aborted + PrintAndLog("Quitting..."); + return 0; + } + if(isOK > 0) + { + PrintAndLog("CSN: %s",sprint_hex(data,8)); + } + if(isOK >= 1) + { + PrintAndLog("CC: %s",sprint_hex(data+8,8)); + }else{ + PrintAndLog("No CC obtained"); + } + } else { + PrintAndLog("Command execute timeout"); + } + } return 0; } @@ -247,17 +394,21 @@ int CmdHFiClassReader_Dump(const char *Cmd) uint8_t CSN[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; uint8_t CCNR[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; //uint8_t CC_temp[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; - uint8_t result[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; - des_context ctx_enc; - uint64_t crypted_id=0; - + uint8_t keytable[128] = {0}; + int elite = 0; + uint8_t *used_key; + int i; if (strlen(Cmd)<1) { - //PrintAndLog("Usage: hf iclass dump "); - //PrintAndLog(" sample: hf iclass dump 0011223344556677 aabbccddeeffgghh FFFFFFFFFFFFFFFF"); - PrintAndLog("Usage: hf iclass dump "); + PrintAndLog("Usage: hf iclass dump [e]"); + PrintAndLog(" Key - A 16 byte master key"); + PrintAndLog(" e - If 'e' is specified, the key is interpreted as the 16 byte"); + PrintAndLog(" Custom Key (KCus), which can be obtained via reader-attack"); + PrintAndLog(" See 'hf iclass sim 2'. This key should be on iclass-format"); PrintAndLog(" sample: hf iclass dump 0011223344556677"); + + return 0; } @@ -266,63 +417,103 @@ int CmdHFiClassReader_Dump(const char *Cmd) PrintAndLog("KEY must include 16 HEX symbols"); return 1; } - - /*if (param_gethex(Cmd, 1, CSN, 16)) + + if (param_getchar(Cmd, 1) == 'e') { - PrintAndLog("CSN must include 16 HEX symbols"); - return 1; + PrintAndLog("Elite switch on"); + elite = 1; + + //calc h2 + hash2(KEY, keytable); + printarr_human_readable("keytable", keytable, 128); + } - if (param_gethex(Cmd, 2, CC_temp, 16)) - { - PrintAndLog("CC must include 16 HEX symbols"); - return 1; - }*/ - - UsbCommand c = {CMD_ICLASS_ISO14443A_GETPUBLIC, {0}}; - //memcpy(c.d.asBytes, MAC, 4); - SendCommand(&c); - + UsbCommand resp; - if (WaitForResponseTimeout(CMD_ACK,&resp,4500)) { - uint8_t isOK = resp.arg[0] & 0xff; - uint8_t * data = resp.d.asBytes; - - memcpy(CSN,data,8); - memcpy(CCNR,data+8,8); - PrintAndLog("DEBUG: %s",sprint_hex(CSN,8)); - PrintAndLog("DEBUG: %s",sprint_hex(CCNR,8)); - PrintAndLog("isOk:%02x", isOK); - } else { - PrintAndLog("Command execute timeout"); + uint8_t key_sel[8] = {0}; + uint8_t key_sel_p[8] = { 0 }; + + //HACK -- Below is for testing without access to a tag + uint8_t fake_dummy_test = false; + if(fake_dummy_test) + { + uint8_t xdata[16] = {0x01,0x02,0x03,0x04,0xF7,0xFF,0x12,0xE0, //CSN from http://www.proxmark.org/forum/viewtopic.php?pid=11230#p11230 + 0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; // Just a random CC. Would be good to add a real testcase here + memcpy(resp.d.asBytes,xdata, 16); + resp.arg[0] = 2; } + //End hack + + + UsbCommand c = {CMD_READER_ICLASS, {0}}; + c.arg[0] = FLAG_ICLASS_READER_ONLY_ONCE; + if(!fake_dummy_test) + SendCommand(&c); - //memcpy(CCNR,CC_temp,8); - des_setkey_enc( &ctx_enc, KEY); - des_crypt_ecb(&ctx_enc,CSN,result); - PrintAndLog("DES Key: %s",sprint_hex(result,8)); - uint64_t newz=0; - crypted_id = bytes_to_num(result,8); - uint64_t x = (crypted_id & 0xFFFF000000000000 ); - pushbackSixBitByte(&newz, getSixBitByte(crypted_id,0),7); - pushbackSixBitByte(&newz, getSixBitByte(crypted_id,1),6); - pushbackSixBitByte(&newz, getSixBitByte(crypted_id,2),5); - pushbackSixBitByte(&newz, getSixBitByte(crypted_id,3),4); - pushbackSixBitByte(&newz, getSixBitByte(crypted_id,4),3); - pushbackSixBitByte(&newz, getSixBitByte(crypted_id,5),2); - pushbackSixBitByte(&newz, getSixBitByte(crypted_id,6),1); - pushbackSixBitByte(&newz, getSixBitByte(crypted_id,7),0); - newz|= x; - crypted_id=newz; - num_to_bytes(crypted_id,8,result); - PrintAndLog("DESr Key: %s",sprint_hex(result,8)); - hash0(crypted_id,div_key); - PrintAndLog("Div Key: %s",sprint_hex(div_key,8)); - calc_iclass_mac(CCNR,12,div_key,MAC); - UsbCommand d = {CMD_READER_ICLASS_REPLAY, {readerType}}; - memcpy(d.d.asBytes, MAC, 4); - SendCommand(&d); + + if (fake_dummy_test || WaitForResponseTimeout(CMD_ACK,&resp,4500)) { + uint8_t isOK = resp.arg[0] & 0xff; + uint8_t * data = resp.d.asBytes; + + memcpy(CSN,data,8); + memcpy(CCNR,data+8,8); + + PrintAndLog("isOk:%02x", isOK); + + if(isOK > 0) + { + PrintAndLog("CSN: %s",sprint_hex(CSN,8)); + } + if(isOK > 1) + { + if(elite) + { + //Get the key index (hash1) + uint8_t key_index[8] = {0}; + + hash1(CSN, key_index); + printvar("hash1", key_index,8); + for(i = 0; i < 8 ; i++) + key_sel[i] = keytable[key_index[i]] & 0xFF; + PrintAndLog("Pre-fortified 'permuted' HS key that would be needed by an iclass reader to talk to above CSN:"); + printvar("k_sel", key_sel,8); + //Permute from iclass format to standard format + permutekey_rev(key_sel,key_sel_p); + used_key = key_sel_p; + }else{ + //Perhaps this should also be permuted to std format? + // Something like the code below? I have no std system + // to test this with /Martin + + //uint8_t key_sel_p[8] = { 0 }; + //permutekey_rev(KEY,key_sel_p); + //used_key = key_sel_p; + + used_key = KEY; + + } + + PrintAndLog("Pre-fortified key that would be needed by the OmniKey reader to talk to above CSN:"); + printvar("Used key",used_key,8); + diversifyKey(CSN,used_key, div_key); + PrintAndLog("Hash0, a.k.a diversified key, that is computed using Ksel and stored in the card (Block 3):"); + printvar("Div key", div_key, 8); + printvar("CC_NR:",CCNR,12); + doMAC(CCNR,12,div_key, MAC); + printvar("MAC", MAC, 4); + + UsbCommand d = {CMD_READER_ICLASS_REPLAY, {readerType}}; + memcpy(d.d.asBytes, MAC, 4); + if(!fake_dummy_test) SendCommand(&d); + + }else{ + PrintAndLog("Failed to obtain CC! Aborting"); + } + } else { + PrintAndLog("Command execute timeout"); + } return 0; } @@ -334,11 +525,8 @@ int CmdHFiClass_iso14443A_write(const char *Cmd) uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; uint8_t CSN[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; uint8_t CCNR[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; - uint8_t CC_temp[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; - uint8_t result[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; - des_context ctx_enc; - uint64_t crypted_id=0; + uint8_t blockNo=0; uint8_t bldata[8]={0}; @@ -367,11 +555,10 @@ int CmdHFiClass_iso14443A_write(const char *Cmd) return 1; } - UsbCommand c = {CMD_ICLASS_ISO14443A_GETPUBLIC, {0}}; - //memcpy(c.d.asBytes, MAC, 4); + UsbCommand c = {CMD_ICLASS_ISO14443A_WRITE, {0}}; SendCommand(&c); - UsbCommand resp; + if (WaitForResponseTimeout(CMD_ACK,&resp,4500)) { uint8_t isOK = resp.arg[0] & 0xff; uint8_t * data = resp.d.asBytes; @@ -384,35 +571,17 @@ int CmdHFiClass_iso14443A_write(const char *Cmd) } else { PrintAndLog("Command execute timeout"); } - - des_setkey_enc( &ctx_enc, KEY); - des_crypt_ecb(&ctx_enc,CSN,result); - PrintAndLog("DES Key: %s",sprint_hex(result,8)); - uint64_t newz=0; - crypted_id = bytes_to_num(result,8); - uint64_t x = (crypted_id & 0xFFFF000000000000 ); - pushbackSixBitByte(&newz, getSixBitByte(crypted_id,0),7); - pushbackSixBitByte(&newz, getSixBitByte(crypted_id,1),6); - pushbackSixBitByte(&newz, getSixBitByte(crypted_id,2),5); - pushbackSixBitByte(&newz, getSixBitByte(crypted_id,3),4); - pushbackSixBitByte(&newz, getSixBitByte(crypted_id,4),3); - pushbackSixBitByte(&newz, getSixBitByte(crypted_id,5),2); - pushbackSixBitByte(&newz, getSixBitByte(crypted_id,6),1); - pushbackSixBitByte(&newz, getSixBitByte(crypted_id,7),0); - newz|= x; - crypted_id=newz; - num_to_bytes(crypted_id,8,result); - PrintAndLog("DESr Key: %s",sprint_hex(result,8)); - hash0(crypted_id,div_key); + + diversifyKey(CSN,KEY, div_key); + PrintAndLog("Div Key: %s",sprint_hex(div_key,8)); - calc_iclass_mac(CCNR,12,div_key,MAC); + doMAC(CCNR, 12,div_key, MAC); - UsbCommand c = {CMD_ICLASS_ISO14443A_WRITE, {readerType,blockNo}}; - memcpy(c.d.asBytes, bldata, 8); - memcpy(c.d.asBytes+8, MAC, 4); - SendCommand(&c); + UsbCommand c2 = {CMD_ICLASS_ISO14443A_WRITE, {readerType,blockNo}}; + memcpy(c2.d.asBytes, bldata, 8); + memcpy(c2.d.asBytes+8, MAC, 4); + SendCommand(&c2); - UsbCommand resp; if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { uint8_t isOK = resp.arg[0] & 0xff; uint8_t * data = resp.d.asBytes;