X-Git-Url: http://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/fb30f5a1013a4e37280c72dda7b37052e317634f..28ee794f59aac1fac7aa18bfbaa4050d48a90260:/client/cmdhflist.c diff --git a/client/cmdhflist.c b/client/cmdhflist.c index 065cbde2..3dd03970 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -21,6 +21,8 @@ #include "iso14443crc.h" #include "parity.h" #include "protocols.h" +#include "crapto1/crapto1.h" +#include "mifarehost.h" enum MifareAuthSeq { @@ -28,11 +30,19 @@ enum MifareAuthSeq { masNt, masNrAr, masAt, + masFirstData, masData, masDataNested, masError, }; static enum MifareAuthSeq MifareAuthState; +static TAuthData AuthData; + +void ClearAuthData() { + AuthData.uid = 0; + AuthData.nt = 0; + AuthData.first_auth = true; +} /** * @brief iso14443A_CRC_check Checks CRC in command or response @@ -63,6 +73,7 @@ uint8_t mifare_CRC_check(bool isResponse, uint8_t* data, uint8_t len) { switch(MifareAuthState) { case masNone: + case masFirstData: case masData: case masDataNested: case masError: @@ -76,7 +87,10 @@ void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) { switch(cmd[0]) { - case ISO14443A_CMD_WUPA: snprintf(exp,size,"WUPA"); break; + case ISO14443A_CMD_WUPA: + snprintf(exp,size,"WUPA"); + MifareAuthState = masNone; + break; case ISO14443A_CMD_ANTICOLL_OR_SELECT:{ // 93 20 = Anticollision (usage: 9320 - answer: 4bytes UID+1byte UID-bytes-xor) // 93 70 = Select (usage: 9370+5bytes 9320 answer - answer: 1byte SAK) @@ -99,7 +113,10 @@ void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) snprintf(exp,size,"ANTICOLL-2"); break; } } - case ISO14443A_CMD_REQA: snprintf(exp,size,"REQA"); break; + case ISO14443A_CMD_REQA: + snprintf(exp,size,"REQA"); + MifareAuthState = masNone; + break; case ISO14443A_CMD_READBLOCK: snprintf(exp,size,"READBLOCK(%d)",cmd[1]); break; case ISO14443A_CMD_WRITEBLOCK: snprintf(exp,size,"WRITEBLOCK(%d)",cmd[1]); break; case ISO14443A_CMD_HALT: @@ -171,23 +188,29 @@ void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) return; } -void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, bool isResponse) { -// uint32_t uid; // UID - static uint32_t nt; // tag challenge -// uint32_t nt_enc; // encrypted tag challenge -// uint8_t nt_enc_par; // encrypted tag challenge parity - static uint32_t nr_enc; // encrypted reader challenge - static uint32_t ar_enc; // encrypted reader response -// uint8_t ar_enc_par; // encrypted reader response parity - static uint32_t at_enc; // encrypted tag response -// uint8_t at_enc_par; // encrypted tag response parity - +void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, uint8_t* parity, uint8_t paritysize, bool isResponse) { + // get UID + if (MifareAuthState == masNone) { + if (cmdsize == 9 && cmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && cmd[1] == 0x70) { + ClearAuthData(); + AuthData.uid = bytes_to_num(&cmd[2], 4); + } + if (cmdsize == 9 && cmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && cmd[1] == 0x70) { + ClearAuthData(); + AuthData.uid = bytes_to_num(&cmd[2], 4); + } + } + switch(MifareAuthState) { case masNt: if (cmdsize == 4 && isResponse) { - snprintf(exp,size,"AUTH: nt %s", (nt) ? "(enc)" : ""); + snprintf(exp,size,"AUTH: nt %s", (AuthData.first_auth) ? "" : "(enc)"); MifareAuthState = masNrAr; - nt = bytes_to_num(cmd, cmdsize); + if (AuthData.first_auth) + AuthData.nt = bytes_to_num(cmd, 4); + else + AuthData.nt_enc = bytes_to_num(cmd, 4); + AuthData.nt_enc_par = parity[0]; return; } else { MifareAuthState = masError; @@ -197,8 +220,9 @@ void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, bool if (cmdsize == 8 && !isResponse) { snprintf(exp,size,"AUTH: nr ar (enc)"); MifareAuthState = masAt; - nr_enc = bytes_to_num(cmd, cmdsize); - ar_enc = bytes_to_num(&cmd[3], cmdsize); + AuthData.nr_enc = bytes_to_num(cmd, 4); + AuthData.ar_enc = bytes_to_num(&cmd[4], 4); + AuthData.ar_enc_par = parity[0] << 4; return; } else { MifareAuthState = masError; @@ -207,8 +231,9 @@ void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, bool case masAt: if (cmdsize == 4 && isResponse) { snprintf(exp,size,"AUTH: at (enc)"); - MifareAuthState = masData; - at_enc = bytes_to_num(cmd, cmdsize); + MifareAuthState = masFirstData; + AuthData.at_enc = bytes_to_num(cmd, 4); + AuthData.at_enc_par = parity[0]; return; } else { MifareAuthState = masError; @@ -222,3 +247,47 @@ void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, bool annotateIso14443a(exp, size, cmd, cmdsize); } + +bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, bool isResponse, uint8_t *mfData, size_t *mfDataLen) { + *mfDataLen = 0; + + if (cmdsize > 32) + return false; + + if (MifareAuthState == masFirstData) { + if (AuthData.first_auth) { + uint32_t ks2 = AuthData.ar_enc ^ prng_successor(AuthData.nt, 64); + uint32_t ks3 = AuthData.at_enc ^ prng_successor(AuthData.nt, 96); + struct Crypto1State *revstate = lfsr_recovery64(ks2, ks3); + lfsr_rollback_word(revstate, 0, 0); + lfsr_rollback_word(revstate, 0, 0); + lfsr_rollback_word(revstate, AuthData.nr_enc, 1); + lfsr_rollback_word(revstate, AuthData.uid ^ AuthData.nt, 0); + + uint64_t lfsr = 0; + crypto1_get_lfsr(revstate, &lfsr); + crypto1_destroy(revstate); +// LastKey = lfsr; + PrintAndLog(" | * | key | probable key:%x%x Prng:%s ks2:%08x ks3:%08x | |", + (unsigned int)((lfsr & 0xFFFFFFFF00000000) >> 32), (unsigned int)(lfsr & 0xFFFFFFFF), + validate_prng_nonce(AuthData.nt) ? "WEAK": "HARD", + ks2, + ks3); + + AuthData.first_auth = false; + } else { + printf("uid:%x nt:%x ar_enc:%x at_enc:%x\n", AuthData.uid, AuthData.nt, AuthData.ar_enc, AuthData.at_enc); + } + + + + MifareAuthState = masData; + return true; + } + + if (MifareAuthState == masData) { + } + + return *mfDataLen > 0; +} +