#include <sys/stat.h>
#include <ctype.h>
#include "iso14443crc.h" // Can also be used for iClass, using 0xE012 as CRC-type
-#include "data.h"
-#include "proxmark3.h"
+#include "comms.h"
#include "ui.h"
#include "cmdparser.h"
#include "cmdhficlass.h"
#include "common.h"
#include "util.h"
#include "cmdmain.h"
-#include "polarssl/des.h"
+#include "mbedtls/des.h"
#include "loclass/cipherutils.h"
#include "loclass/cipher.h"
#include "loclass/ikeys.h"
#include "usb_cmd.h"
#include "cmdhfmfu.h"
#include "util_posix.h"
+#include "cmdhf14a.h" // DropField()
static int CmdHelp(const char *Cmd);
} iclass_block_t;
int usage_hf_iclass_chk(void) {
- PrintAndLog("Usage: hf iclass chk [h] <f (*.dic)>");
+ PrintAndLog("Checkkeys loads a dictionary text file with 8byte hex keys to test authenticating against a iClass tag");
+ PrintAndLog("Usage: hf iclass chk [h|e|r] <f (*.dic)>");
PrintAndLog("Options:");
PrintAndLog("h Show this help");
PrintAndLog("f <filename> Dictionary file with default iclass keys");
+ PrintAndLog(" e target Elite / High security key scheme");
+ PrintAndLog(" r interpret dictionary file as raw (diversified keys)");
+ PrintAndLog("Samples:");
+ PrintAndLog(" hf iclass chk f default_iclass_keys.dic");
+ PrintAndLog(" hf iclass chk f default_iclass_keys.dic e");
return 0;
}
return 0;
}
+// the original malicious IDs from Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult,
+// and Milosch Meriac. Dismantling iClass and iClass Elite.
#define NUM_CSNS 15
+static 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 };
+
+
+// pre-defined 9 CSNs by iceman.
+// only one csn depend on several others.
+// six depends only on the first csn, (0,1, 0x45)
+
+// #define NUM_CSNS 9
+// static uint8_t csns[8 * NUM_CSNS] = {
+ // 0x01, 0x0A, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0,
+ // 0x0C, 0x06, 0x0C, 0xFE, 0xF7, 0xFF, 0x12, 0xE0,
+ // 0x10, 0x97, 0x83, 0x7B, 0xF7, 0xFF, 0x12, 0xE0,
+ // 0x13, 0x97, 0x82, 0x7A, 0xF7, 0xFF, 0x12, 0xE0,
+ // 0x07, 0x0E, 0x0D, 0xF9, 0xF7, 0xFF, 0x12, 0xE0,
+ // 0x14, 0x96, 0x84, 0x76, 0xF7, 0xFF, 0x12, 0xE0,
+ // 0x17, 0x96, 0x85, 0x71, 0xF7, 0xFF, 0x12, 0xE0,
+ // 0xCE, 0xC5, 0x0F, 0x77, 0xF7, 0xFF, 0x12, 0xE0,
+ // 0xD2, 0x5A, 0x82, 0xF8, 0xF7, 0xFF, 0x12, 0xE0
+ // //0x04, 0x08, 0x9F, 0x78, 0x6E, 0xFF, 0x12, 0xE0
+// };
+
+
int CmdHFiClassSim(const char *Cmd) {
uint8_t simType = 0;
uint8_t CSN[8] = {0, 0, 0, 0, 0, 0, 0, 0};
- if (strlen(Cmd)<1) {
+ if (strlen(Cmd) < 1) {
return usage_hf_iclass_sim();
}
simType = param_get8ex(Cmd, 0, 0, 10);
- if(simType == 0)
- {
+ if (simType == ICLASS_SIM_MODE_CSN) {
if (param_gethex(Cmd, 1, CSN, 16)) {
PrintAndLog("A CSN should consist of 16 HEX symbols");
return usage_hf_iclass_sim();
}
-
PrintAndLog("--simtype:%02x csn:%s", simType, sprint_hex(CSN, 8));
}
- if(simType > 3)
- {
- PrintAndLog("Undefined simptype %d", simType);
- return usage_hf_iclass_sim();
- }
- uint8_t numberOfCSNs=0;
- if(simType == 2)
- {
- UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType,NUM_CSNS}};
+ if (simType == ICLASS_SIM_MODE_READER_ATTACK) {
+ 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, 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);
+ memcpy(c.d.asBytes, csns, 8 * NUM_CSNS);
SendCommand(&c);
if (!WaitForResponseTimeout(CMD_ACK, &resp, -1)) {
}
uint8_t num_mac_responses = resp.arg[1];
- PrintAndLog("Mac responses: %d MACs obtained (should be %d)", num_mac_responses,NUM_CSNS);
+ PrintAndLog("Mac responses: %d MACs obtained (should be %d)", num_mac_responses, NUM_CSNS);
- size_t datalen = NUM_CSNS*24;
+ 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>....
* 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
+ * <8 byte CC><4 byte NR><4 byte MAC>
+ * 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...
+ for(int i = 0; i < NUM_CSNS; i++) {
+ memcpy(dump + i*24, csns+i*8, 8); //CSN
+ //copy CC from response
+ memcpy(dump + i*24 + 8, resp.d.asBytes + i*16, 8);
//Then comes NR_MAC (eight bytes from the response)
- memcpy(dump+i*24+16,resp.d.asBytes+i*8,8);
-
+ memcpy(dump + i*24 + 16, resp.d.asBytes + i*16 + 8, 8);
}
/** Now, save to dumpfile **/
saveFile("iclass_mac_attack", "bin", dump,datalen);
free(dump);
- }else
- {
- UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType,numberOfCSNs}};
+
+ } else if (simType == ICLASS_SIM_MODE_CSN || simType == ICLASS_SIM_MODE_CSN_DEFAULT || simType == ICLASS_SIM_MODE_FULL) {
+ UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType, 0}};
memcpy(c.d.asBytes, CSN, 8);
SendCommand(&c);
+
+ } else {
+ PrintAndLog("Undefined simtype %d", simType);
+ return usage_hf_iclass_sim();
}
return 0;
fseek(f, 0, SEEK_SET);
uint8_t enc_dump[8] = {0};
uint8_t *decrypted = malloc(fsize);
- des3_context ctx = { DES_DECRYPT ,{ 0 } };
- des3_set2key_dec( &ctx, key);
+ mbedtls_des3_context ctx = { {0} };
+ mbedtls_des3_set2key_dec( &ctx, key);
size_t bytes_read = fread(enc_dump, 1, 8, f);
//Use the first block (CSN) for filename
{
memcpy(decrypted+(blocknum*8), enc_dump, 8);
}else{
- des3_crypt_ecb(&ctx, enc_dump,decrypted +(blocknum*8) );
+ mbedtls_des3_crypt_ecb(&ctx, enc_dump,decrypted +(blocknum*8) );
}
printvar("decrypted block", decrypted +(blocknum*8), 8);
bytes_read = fread(enc_dump, 1, 8, f);
uint8_t encryptedData[16];
uint8_t *encrypted = encryptedData;
- des3_context ctx = { DES_DECRYPT ,{ 0 } };
- des3_set2key_enc( &ctx, key);
+ mbedtls_des3_context ctx = { {0} };
+ mbedtls_des3_set2key_enc( &ctx, key);
- des3_crypt_ecb(&ctx, blkData,encrypted);
+ mbedtls_des3_crypt_ecb(&ctx, blkData,encrypted);
//printvar("decrypted block", decrypted, 8);
memcpy(blkData,encrypted,8);
blocksRead = (sizeof(tag_data)/8) - blockno;
}
// response ok - now get bigbuf content of the dump
- GetFromBigBuf(tag_data+(blockno*8), blocksRead*8, startindex);
- WaitForResponse(CMD_ACK,NULL);
+ GetFromBigBuf(tag_data+(blockno*8), blocksRead*8, startindex, NULL, -1, false);
size_t gotBytes = blocksRead*8 + blockno*8;
// try AA2
blocksRead = (sizeof(tag_data) - gotBytes)/8;
}
// get dumped data from bigbuf
- GetFromBigBuf(tag_data+gotBytes, blocksRead*8, startindex);
- WaitForResponse(CMD_ACK,NULL);
+ GetFromBigBuf(tag_data+gotBytes, blocksRead*8, startindex, NULL, -1, false);
gotBytes += blocksRead*8;
} else { //field is still on - turn it off...
return 0;
}
char fileName[255] = {0};
- if(opt == 'f')
- {
- if(param_getstr(Cmd, 1, fileName, sizeof(fileName)) > 0)
- {
+ if(opt == 'f') {
+ if(param_getstr(Cmd, 1, fileName, sizeof(fileName)) > 0) {
return bruteforceFileNoKeys(fileName);
- }else
- {
+ } else {
PrintAndLog("You must specify a filename");
}
- }
- else if(opt == 't')
- {
+ } else if(opt == 't') {
int errors = testCipherUtils();
errors += testMAC();
errors += doKeyTests(0);
errors += testElite();
- if(errors)
- {
+ if(errors) {
prnlog("OBS! There were errors!!!");
}
return errors;
int CmdHFiClassCheckKeys(const char *Cmd) {
- char ctmp = 0x00;
- ctmp = param_getchar(Cmd, 0);
- if (ctmp == 'h' || ctmp == 'H') return usage_hf_iclass_chk();
-
uint8_t mac[4] = {0x00,0x00,0x00,0x00};
uint8_t key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t div_key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
// elite key, raw key, standard key
- bool elite = false;
- bool rawkey = false;
+ bool use_elite = false;
+ bool use_raw = false;
bool found_debit = false;
bool found_credit = false;
-
+ bool errors = false;
+ uint8_t cmdp = 0x00;
FILE * f;
char filename[FILE_PATH_SIZE] = {0};
+ uint8_t fileNameLen = 0;
char buf[17];
uint8_t *keyBlock = NULL, *p;
int keyitems = 0, keycnt = 0;
-
- // May be a dictionary file
- if ( param_getstr(Cmd, 1, filename, sizeof(filename)) >= FILE_PATH_SIZE ) {
- PrintAndLog("File name too long");
- free(keyBlock);
- return 2;
+ while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
+ switch (param_getchar(Cmd, cmdp)) {
+ case 'h':
+ case 'H':
+ return usage_hf_iclass_chk();
+ case 'f':
+ case 'F':
+ fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename));
+ if (fileNameLen < 1) {
+ PrintAndLog("No filename found after f");
+ errors = true;
+ }
+ cmdp += 2;
+ break;
+ case 'e':
+ case 'E':
+ use_elite = true;
+ cmdp++;
+ break;
+ case 'r':
+ case 'R':
+ use_raw = true;
+ cmdp++;
+ break;
+ default:
+ PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
+ errors = true;
+ break;
+ }
}
+ if (errors) return usage_hf_iclass_chk();
if ( !(f = fopen( filename , "r")) ) {
PrintAndLog("File: %s: not found or locked.", filename);
- free(keyBlock);
return 1;
}
// debit key. try twice
for (int foo = 0; foo < 2 && !found_debit; foo++) {
- if (!select_and_auth(key, mac, div_key, false, elite, rawkey, false))
+ if (!select_and_auth(key, mac, div_key, false, use_elite, use_raw, false))
continue;
// key found.
// credit key. try twice
for (int foo = 0; foo < 2 && !found_credit; foo++) {
- if (!select_and_auth(key, mac, div_key, true, elite, rawkey, false))
+ if (!select_and_auth(key, mac, div_key, true, use_elite, use_raw, false))
continue;
// key found