X-Git-Url: http://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/20f9a2a1d54952ed15066c93490f0e8fb0d43b67..f397b5cc874ac7d658173199d92c30f3f717a300:/armsrc/mifareutil.c diff --git a/armsrc/mifareutil.c b/armsrc/mifareutil.c index ede1cbc9..53e785f5 100644 --- a/armsrc/mifareutil.c +++ b/armsrc/mifareutil.c @@ -19,11 +19,18 @@ #include "crapto1.h" #include "mifareutil.h" +int MF_DBGLEVEL = MF_DBG_ALL; + uint8_t* mifare_get_bigbufptr(void) { return (((uint8_t *)BigBuf) + 3560); // was 3560 - tied to other size changes } int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer) +{ + return mifare_sendcmd_shortex(pcs, crypted, cmd, data, answer, NULL); +} + +int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint32_t * parptr) { uint8_t dcmd[4], ecmd[4]; uint32_t pos, par, res; @@ -48,9 +55,11 @@ int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, ReaderTransmit(dcmd, sizeof(dcmd)); } - int len = ReaderReceive(answer); + int len = ReaderReceivePar(answer, &par); + + if (parptr) *parptr = par; - if (crypted) { + if (crypted == CRYPT_ALL) { if (len == 1) { res = 0; for (pos = 0; pos < 4; pos++) @@ -70,22 +79,27 @@ int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, } int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint64_t isNested) +{ + return mifare_classic_authex(pcs, uid, blockNo, keyType, ui64Key, isNested, NULL); +} + +int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint64_t isNested, uint32_t * ntptr) { // variables - int len; + int len; uint32_t pos; uint8_t tmp4[4]; - byte_t par = 0; - byte_t ar[4]; + byte_t par = 0; + byte_t ar[4]; uint32_t nt, ntpp; // Supplied tag nonce uint8_t mf_nr_ar[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; - uint8_t* receivedAnswer = mifare_get_bigbufptr(); + uint8_t* receivedAnswer = mifare_get_bigbufptr(); - // Transmit MIFARE_CLASSIC_AUTH + // Transmit MIFARE_CLASSIC_AUTH len = mifare_sendcmd_short(pcs, isNested, 0x60 + (keyType & 0x01), blockNo, receivedAnswer); -// Dbprintf("rand nonce len: %x", len); - if (len != 4) return 1; + if (MF_DBGLEVEL >= 4) Dbprintf("rand nonce len: %x", len); + if (len != 4) return 1; ar[0] = 0x55; ar[1] = 0x41; @@ -94,50 +108,65 @@ int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, // Save the tag nonce (nt) nt = bytes_to_num(receivedAnswer, 4); - Dbprintf("uid: %x nt: %x", uid, nt); // ----------------------------- crypto1 create - // Init cipher with key + if (isNested) + crypto1_destroy(pcs); + + // Init cipher with key crypto1_create(pcs, ui64Key); - // Load (plain) uid^nt into the cipher - crypto1_word(pcs, nt ^ uid, 0); + if (isNested == AUTH_NESTED) { + // decrypt nt with help of new key + nt = crypto1_word(pcs, nt ^ uid, 1) ^ nt; + } else { + // Load (plain) uid^nt into the cipher + crypto1_word(pcs, nt ^ uid, 0); + } + + // some statistic + if (!ntptr && (MF_DBGLEVEL >= 3)) + Dbprintf("auth uid: %08x nt: %08x", uid, nt); + + // save Nt + if (ntptr) + *ntptr = nt; par = 0; - // Generate (encrypted) nr+parity by loading it into the cipher (Nr) - for (pos = 0; pos < 4; pos++) - { - mf_nr_ar[pos] = crypto1_byte(pcs, ar[pos], 0) ^ ar[pos]; + // Generate (encrypted) nr+parity by loading it into the cipher (Nr) + for (pos = 0; pos < 4; pos++) + { + mf_nr_ar[pos] = crypto1_byte(pcs, ar[pos], 0) ^ ar[pos]; par = (par >> 1) | ( ((filter(pcs->odd) ^ oddparity(ar[pos])) & 0x01) * 0x80 ); - } + } - // Skip 32 bits in pseudo random generator - nt = prng_successor(nt,32); + // Skip 32 bits in pseudo random generator + nt = prng_successor(nt,32); // ar+parity - for (pos = 4; pos < 8; pos++) - { + for (pos = 4; pos < 8; pos++) + { nt = prng_successor(nt,8); - mf_nr_ar[pos] = crypto1_byte(pcs,0x00,0) ^ (nt & 0xff); + mf_nr_ar[pos] = crypto1_byte(pcs,0x00,0) ^ (nt & 0xff); par = (par >> 1)| ( ((filter(pcs->odd) ^ oddparity(nt & 0xff)) & 0x01) * 0x80 ); - } + } - // Transmit reader nonce and reader answer - ReaderTransmitPar(mf_nr_ar, sizeof(mf_nr_ar), par); + // Transmit reader nonce and reader answer + ReaderTransmitPar(mf_nr_ar, sizeof(mf_nr_ar), par); - // Receive 4 bit answer + // Receive 4 bit answer len = ReaderReceive(receivedAnswer); - if (!len) - { - Dbprintf("Authentication failed. Card timeout."); + if (!len) + { + if (MF_DBGLEVEL >= 1) Dbprintf("Authentication failed. Card timeout."); return 2; - } + } - memcpy(tmp4, receivedAnswer, 4); + memcpy(tmp4, receivedAnswer, 4); ntpp = prng_successor(nt, 32) ^ crypto1_word(pcs, 0,0); if (ntpp != bytes_to_num(tmp4, 4)) { - Dbprintf("Authentication failed. Error card response."); + if (MF_DBGLEVEL >= 1) Dbprintf("Authentication failed. Error card response."); return 3; } @@ -147,26 +176,26 @@ int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData) { // variables - int len; + int len; uint8_t bt[2]; - uint8_t* receivedAnswer = mifare_get_bigbufptr(); + uint8_t* receivedAnswer = mifare_get_bigbufptr(); - // command MIFARE_CLASSIC_READBLOCK + // command MIFARE_CLASSIC_READBLOCK len = mifare_sendcmd_short(pcs, 1, 0x30, blockNo, receivedAnswer); if (len == 1) { - Dbprintf("Cmd Error: %02x", receivedAnswer[0]); + if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); return 1; } if (len != 18) { - Dbprintf("Cmd Error: card timeout. len: %x", len); + if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Error: card timeout. len: %x", len); return 2; } memcpy(bt, receivedAnswer + 16, 2); - AppendCrc14443a(receivedAnswer, 16); + AppendCrc14443a(receivedAnswer, 16); if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) { - Dbprintf("Cmd CRC response error."); + if (MF_DBGLEVEL >= 1) Dbprintf("Cmd CRC response error."); return 3; } @@ -177,19 +206,19 @@ int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blo int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData) { // variables - int len, i; + int len, i; uint32_t pos; - uint32_t par = 0; - byte_t res; + uint32_t par = 0; + byte_t res; uint8_t d_block[18], d_block_enc[18]; - uint8_t* receivedAnswer = mifare_get_bigbufptr(); + uint8_t* receivedAnswer = mifare_get_bigbufptr(); - // command MIFARE_CLASSIC_WRITEBLOCK + // command MIFARE_CLASSIC_WRITEBLOCK len = mifare_sendcmd_short(pcs, 1, 0xA0, blockNo, receivedAnswer); if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK - Dbprintf("Cmd Error: %02x", receivedAnswer[0]); + if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); return 1; } @@ -198,15 +227,15 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl // crypto par = 0; - for (pos = 0; pos < 18; pos++) - { - d_block_enc[pos] = crypto1_byte(pcs, 0x00, 0) ^ d_block[pos]; + for (pos = 0; pos < 18; pos++) + { + d_block_enc[pos] = crypto1_byte(pcs, 0x00, 0) ^ d_block[pos]; par = (par >> 1) | ( ((filter(pcs->odd) ^ oddparity(d_block[pos])) & 0x01) * 0x20000 ); - } + } - ReaderTransmitPar(d_block_enc, sizeof(d_block_enc), par); + ReaderTransmitPar(d_block_enc, sizeof(d_block_enc), par); - // Receive the response + // Receive the response len = ReaderReceive(receivedAnswer); res = 0; @@ -214,7 +243,7 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], i)) << i; if ((len != 1) || (res != 0x0A)) { - Dbprintf("Cmd send data2 Error: %02x", res); + if (MF_DBGLEVEL >= 1) Dbprintf("Cmd send data2 Error: %02x", res); return 2; } @@ -224,14 +253,14 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid) { // variables - int len; + int len; // Mifare HALT - uint8_t* receivedAnswer = mifare_get_bigbufptr(); + uint8_t* receivedAnswer = mifare_get_bigbufptr(); len = mifare_sendcmd_short(pcs, 1, 0x50, 0x00, receivedAnswer); - if (len != 0) { - Dbprintf("halt error. response len: %x", len); + if (len != 0) { + if (MF_DBGLEVEL >= 1) Dbprintf("halt error. response len: %x", len); return 1; }