X-Git-Url: http://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/20f9a2a1d54952ed15066c93490f0e8fb0d43b67..4abe4f5867e52615c0e053a2bab4b3b129b12d45:/armsrc/mifareutil.c diff --git a/armsrc/mifareutil.c b/armsrc/mifareutil.c index ede1cbc9..59dafedc 100644 --- a/armsrc/mifareutil.c +++ b/armsrc/mifareutil.c @@ -50,7 +50,7 @@ int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, int len = ReaderReceive(answer); - if (crypted) { + if (crypted == CRYPT_ALL) { if (len == 1) { res = 0; for (pos = 0; pos < 4; pos++) @@ -72,20 +72,20 @@ 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) { // 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 (len != 4) return 1; ar[0] = 0x55; ar[1] = 0x41; @@ -94,50 +94,60 @@ 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 + Dbprintf("auth uid: %08x nt: %08x", uid, 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) + { + 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."); + Dbprintf("Authentication failed. Error card response."); return 3; } @@ -147,12 +157,12 @@ 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]); @@ -164,7 +174,7 @@ int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blo } 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."); return 3; @@ -177,15 +187,15 @@ 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 @@ -198,15 +208,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; @@ -224,13 +234,13 @@ 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) { + if (len != 0) { Dbprintf("halt error. response len: %x", len); return 1; }