From fe9416db2357fea1693d9cbb898e58adf3aae402 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 2 Jan 2018 11:17:31 +0100 Subject: [PATCH] chg: 'hf iclass' - work in progress. running default_iclass_keys.dic against reader (pm3 as simulation) --- armsrc/iclass.c | 7 +- client/cmdhficlass.c | 240 +++++++++++++++++++++++++++---------------- client/cmdhficlass.h | 19 +++- 3 files changed, 171 insertions(+), 95 deletions(-) diff --git a/armsrc/iclass.c b/armsrc/iclass.c index 096266a07..c9a5db465 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -2095,10 +2095,9 @@ void iClass_Authentication(uint8_t *mac) { cmd_send(CMD_ACK,isOK,0,0,0,0); } -typedef struct iclass_precalc { - //uint8_t key[8]; +typedef struct iclass_premac { uint8_t mac[4]; -} iclass_precalc_t; +} iclass_premac_t; /* this function works on the following assumptions. * - one select first, to get CSN / CC (e-purse) @@ -2122,7 +2121,7 @@ void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain) { // select card / e-purse uint8_t card_data[6 * 8] = {0}; - iclass_precalc_t *keys = (iclass_precalc_t *)datain; + iclass_premac_t *keys = (iclass_premac_t *)datain; LED_A_ON(); diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index 0b6e15d0c..578f625b6 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -216,12 +216,13 @@ int usage_hf_iclass_loclass(void) { } int usage_hf_iclass_chk(void) { 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] "); + PrintAndLog("Usage: hf iclass chk [h|e|r] [f (*.dic)] [c ] [p ] [m ]"); PrintAndLog("Options:"); PrintAndLog(" h Show this help"); PrintAndLog(" f Dictionary file with default iclass keys"); - PrintAndLog(" e target Elite / High security key scheme"); - PrintAndLog(" r interpret dictionary file as raw (diversified keys)"); + PrintAndLog(" c CSN"); + PrintAndLog(" p EPURSE"); + PrintAndLog(" m macs"); PrintAndLog("Samples:"); PrintAndLog(" hf iclass chk f default_iclass_keys.dic"); PrintAndLog(" hf iclass chk f default_iclass_keys.dic e"); @@ -1823,7 +1824,7 @@ int CmdHFiClassCheckKeys(const char *Cmd) { uint8_t fileNameLen = 0; uint8_t *keyBlock = NULL; - iclass_precalc_t *pre = NULL; + iclass_premac_t *pre = NULL; int keycnt = 0; // time @@ -1879,13 +1880,13 @@ int CmdHFiClassCheckKeys(const char *Cmd) { } // load keys into keyblock - int res = ReadDictionaryKeyFile( filename, &keyBlock, &keycnt); + int res = LoadDictionaryKeyFile( filename, &keyBlock, &keycnt); if ( res > 0) { free(keyBlock); return 1; } - pre = calloc(keycnt, sizeof(iclass_precalc_t)); + pre = calloc(keycnt, sizeof(iclass_premac_t)); if ( !pre ) { free(keyBlock); return 1; @@ -1984,50 +1985,49 @@ out: PrintAndLog(""); return 0; } + static int cmp_uint32( const void *a, const void *b) { - if (*(const uint32_t *)a < *(const uint32_t *)b) + + const iclass_prekey_t* x = (const iclass_prekey_t *)a; + const iclass_prekey_t* y = (const iclass_prekey_t *)b; + + uint32_t mx = bytes_to_num( (uint8_t*)x->mac, 4); + uint32_t my = bytes_to_num( (uint8_t*)y->mac, 4); + + if (mx < my) return -1; else - return *(const uint32_t *)a > *(const uint32_t *)b; -} -static inline uint32_t binsearch(uint32_t key, uint32_t v[], size_t n){ - int low, high, mid; - low = 0; - high = n - 1; - while (low <= high) { - mid = (low+high)/2; - if (key < v[mid]) - high = mid + 1; - else if (key > v[mid]) - low = mid + 1; - else /* found match */ - return mid; - } - return -1; /* no match */ + return mx > my; } -int ReaderEliteLookUp(const char *Cmd) { +// binary search in struct iclass_prekey_t for mac +// static inline int32_t binsearch(uint32_t key, iclass_prekey_t* v, size_t n){ + // int mid, low = 0, high = n - 1; + // uint32_t m; + // while (low <= high) { + + // mid = (low+high)/2; + // m = bytes_to_num( v[mid].mac, 4); + + // if (key < m) + // high = mid - 1; + // else if (key > m) + // low = mid + 1; + // else /* found match */ + // return mid; + // } + // return -1; /* no match */ +// } + +// this method tries to identify in which configuration mode a iClass / iClass SE reader is in. +// Standard or Elite / HighSecurity mode. It uses a default key dictionary list in order to work. +int CmdHFiClassLookUp(const char *Cmd) { - // SIM / sniff, - // reader tries to authenticate AA1 -> - // legacy key - // - // or - // elite key - // ladda nycklar. - // sortera nycklar, mac på mac qsort - // leta upp mac binsearch, - // om funnen, printa - // load keys into keyblock - 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 key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; - uint8_t div_key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; - uint8_t mac_legacy[4] = {0x00,0x00,0x00,0x00}; - uint8_t mac_elite[4] = {0x00,0x00,0x00,0x00}; + uint8_t CSN[8]; + uint8_t EPURSE[8]; + uint8_t MACS[8]; + uint8_t MAC_TAG[4] = {0x00,0x00,0x00,0x00}; - */ // elite key, raw key, standard key bool use_elite = false; bool use_raw = false; @@ -2038,8 +2038,8 @@ int ReaderEliteLookUp(const char *Cmd) { uint8_t fileNameLen = 0; uint8_t *keyBlock = NULL; - iclass_precalc_t *pre = NULL; - int keycnt = 0; + iclass_prekey_t *prekey = NULL; + int keycnt = 0, len = 0; // time uint64_t t1 = msclock(); @@ -2058,6 +2058,36 @@ int ReaderEliteLookUp(const char *Cmd) { } cmdp += 2; break; + case 'u': + case 'U': + param_gethex_ex(Cmd, cmdp+1, CSN, &len); + if ( len>>1 != sizeof(CSN) ) { + PrintAndLog("Wrong CSN length, expected %d got [%d]", sizeof(CSN), len>>1); + errors = true; + } + cmdp += 2; + break; + case 'm': + case 'M': + param_gethex_ex(Cmd, cmdp+1, MACS, &len); + if ( len>>1 != sizeof(MACS) ) { + PrintAndLog("Wrong MACS length, expected %d got [%d] ", sizeof(MACS), len>>1); + errors = true; + } else { + memcpy(MAC_TAG, MACS+4, 4); + } + cmdp += 2; + break; + case 'p': + case 'P': + param_gethex_ex(Cmd, cmdp+1, EPURSE, &len); + if ( len>>1 != sizeof(EPURSE) ) { + PrintAndLog("Wrong EPURSE length, expected %d got [%d] ", sizeof(EPURSE), len>>1); + errors = true; + } + cmdp += 2; + break; + break; case 'e': case 'E': use_elite = true; @@ -2075,54 +2105,60 @@ int ReaderEliteLookUp(const char *Cmd) { } } if (errors) return usage_hf_iclass_chk(); - - int res = ReadDictionaryKeyFile( filename, &keyBlock, &keycnt); - if ( res > 0) { - free(keyBlock); - return 1; - } - - pre = calloc(keycnt, sizeof(iclass_precalc_t)); - if ( !pre ) { - free(keyBlock); - return 1; - } + + PrintAndLog("CSN %s", sprint_hex( CSN, sizeof(CSN) )); + PrintAndLog("Epurse %s", sprint_hex( EPURSE, sizeof(EPURSE) )); + PrintAndLog("MACS %s", sprint_hex( MACS, sizeof(MACS) )); + PrintAndLog("MAC_TAG %s", sprint_hex( MAC_TAG, sizeof(MAC_TAG) )); - PrintAndLog("[+] Generating diversified keys and MAC"); - res = GenerateMacFromKeyFile( CSN, CCNR, use_raw, use_elite, keyBlock, keycnt, pre ); + int res = LoadDictionaryKeyFile( filename, &keyBlock, &keycnt); if ( res > 0) { free(keyBlock); - free(pre); + return 1; + } + //iclass_prekey_t + prekey = calloc(keycnt, sizeof(iclass_prekey_t)); + if ( !prekey ) { + free(keyBlock); + return 1; + } + + PrintAndLog("[-] Generating diversified keys and MAC"); + res = GenerateFromKeyFile( CSN, EPURSE, use_raw, use_elite, keyBlock, keycnt, prekey ); + if ( res > 0) { + free(keyBlock); + free(prekey); return 1; } - - // qsort - // qsort( pre, sizeof(iclass_precalc_t), cmp_uint32); - // binsearch(mac_elite, pre, keycnt) - - // memcpy(div_key, key, 8); - // doMAC(CCNR, div_key, mac_legacy); - - - // if (use_raw) - // memcpy(div_key, key, 8); - // else - // HFiClassCalcDivKey(CSN, key, div_key, use_elite); + PrintAndLog("[-] Sorting"); + + // sort mac list. + qsort( prekey, keycnt, sizeof(iclass_prekey_t), cmp_uint32); + + //PrintPreCalc(prekey, keycnt); + + PrintAndLog("[-] Searching"); + iclass_prekey_t *item; + iclass_prekey_t lookup; + memcpy(lookup.mac, MAC_TAG, 4); + + // using find + item = (iclass_prekey_t*) bsearch(&lookup, prekey, keycnt, sizeof(iclass_prekey_t), cmp_uint32); + if( item != NULL ) { + PrintAndLog("\n[+] [debit] found key %s", sprint_hex(item->key, 8)); + } - // doMAC(CCNR, div_key, pre_list[i].mac); t1 = msclock() - t1; - PrintAndLog("\nTime in iclass : %.0f seconds\n", (float)t1/1000.0); - DropField(); - free(pre); + free(prekey); free(keyBlock); PrintAndLog(""); return 0; } -int ReadDictionaryKeyFile( char* filename, uint8_t **keys, int *keycnt) { +int LoadDictionaryKeyFile( char* filename, uint8_t **keys, int *keycnt) { char buf[17]; FILE * f; @@ -2172,7 +2208,7 @@ int ReadDictionaryKeyFile( char* filename, uint8_t **keys, int *keycnt) { } // precalc diversified keys and their MAC -int GenerateMacFromKeyFile( uint8_t* CSN, uint8_t* CCNR, bool use_raw, bool use_elite, uint8_t* keys, int keycnt, iclass_precalc_t* pre_list ) { +int GenerateMacFromKeyFile( uint8_t* CSN, uint8_t* CCNR, bool use_raw, bool use_elite, uint8_t* keys, int keycnt, iclass_premac_t* list ) { 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}; @@ -2185,24 +2221,54 @@ int GenerateMacFromKeyFile( uint8_t* CSN, uint8_t* CCNR, bool use_raw, bool use_ else HFiClassCalcDivKey(CSN, key, div_key, use_elite); - doMAC(CCNR, div_key, pre_list[i].mac); + doMAC(CCNR, div_key, list[i].mac); + } + return 0; +} + +int GenerateFromKeyFile( uint8_t* CSN, uint8_t* CCNR, bool use_raw, bool use_elite, uint8_t* keys, int keycnt, iclass_prekey_t* list ) { + + uint8_t div_key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + + for ( int i=0; i < keycnt; i++) { + + memcpy(list[i].key, keys + 8 * i , 8); + + // generate diversifed key + if (use_raw) + memcpy(div_key, list[i].key, 8); + else + HFiClassCalcDivKey(CSN, list[i].key, div_key, use_elite); + + // generate MAC + doMAC(CCNR, div_key, list[i].mac); } return 0; } // print diversified keys -void PrintPreCalcMac(uint8_t* keys, int keycnt, iclass_precalc_t* pre_list) { +void PrintPreCalcMac(uint8_t* keys, int keycnt, iclass_premac_t* pre_list) { - uint8_t key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + iclass_prekey_t* b = calloc(keycnt, sizeof(iclass_prekey_t)); + if ( !b ) + return; + + for ( int i=0; i < keycnt; i++) { + memcpy(b[i].key, keys + 8 * i , 8); + memcpy(b[i].mac, pre_list[i].mac, 4); + } + PrintPreCalc(b, keycnt); + free(b); +} + +void PrintPreCalc(iclass_prekey_t* list, int itemcnt) { PrintAndLog("-----+------------------+---------"); PrintAndLog("#key | key | mac"); PrintAndLog("-----+------------------+---------"); - for ( int i=0; i < keycnt; i++) { - - memcpy(key, keys + 8 * i , 8); + for ( int i=0; i < itemcnt; i++) { if (i < 10 ) { - PrintAndLog("[%2d] | %016" PRIx64 " | %08" PRIx32, i, bytes_to_num(key, 8), bytes_to_num( pre_list[i].mac, 4) ); + PrintAndLog("[%2d] | %016" PRIx64 " | %08" PRIx32, i, bytes_to_num(list[i].key, 8), bytes_to_num( list[i].mac, 4) ); } else if ( i == 10 ) { PrintAndLog("... skip printing the rest"); } @@ -2228,6 +2294,8 @@ static command_t CommandTable[] = { {"sim", CmdHFiClassSim, 0, "[options..] Simulate iClass tag"}, {"sniff", CmdHFiClassSniff, 0, " Eavesdrop iClass communication"}, {"writeblk", CmdHFiClass_WriteBlock, 0, "[options..] Authenticate and Write iClass block"}, + {"a", CmdHFiClassLookUp, 0, "[options..] A"}, + {NULL, NULL, 0, NULL} }; diff --git a/client/cmdhficlass.h b/client/cmdhficlass.h index 0c2535e8b..ca7b4a154 100644 --- a/client/cmdhficlass.h +++ b/client/cmdhficlass.h @@ -42,9 +42,14 @@ typedef struct iclass_block { uint8_t d[8]; } iclass_block_t; -typedef struct iclass_precalc { +typedef struct iclass_premac { uint8_t mac[4]; -} iclass_precalc_t; +} iclass_premac_t; + +typedef struct iclass_prekey { + uint8_t mac[4]; + uint8_t key[8]; +} iclass_prekey_t; int CmdHFiClass(const char *Cmd); @@ -69,9 +74,13 @@ extern int CmdHFiClassSim(const char *Cmd); extern int CmdHFiClassWriteKeyFile(const char *Cmd); extern int CmdHFiClass_WriteBlock(const char *Cmd); extern int CmdHF14AMfChk(const char *Cmd); + void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t endblock, size_t filesize); void HFiClassCalcDivKey(uint8_t *CSN, uint8_t *KEY, uint8_t *div_key, bool elite); -int ReadDictionaryKeyFile( char* filename, uint8_t **keys, int *keycnt); -int GenerateMacFromKeyFile( uint8_t* CSN, uint8_t* CCNR, bool use_raw, bool use_elite, uint8_t* keys, int keycnt, iclass_precalc_t* pre_list ); -void PrintPreCalcMac(uint8_t* keys, int keycnt, iclass_precalc_t* pre_list); + +int LoadDictionaryKeyFile( char* filename, uint8_t **keys, int *keycnt); +int GenerateMacFromKeyFile( uint8_t* CSN, uint8_t* CCNR, bool use_raw, bool use_elite, uint8_t* keys, int keycnt, iclass_premac_t* list ); +int GenerateFromKeyFile( uint8_t* CSN, uint8_t* CCNR, bool use_raw, bool use_elite, uint8_t* keys, int keycnt, iclass_prekey_t* list ); +void PrintPreCalcMac(uint8_t* keys, int keycnt, iclass_premac_t* pre_list); +void PrintPreCalc(iclass_prekey_t* list, int itemcnt); #endif