From: Oleg Moiseenko Date: Thu, 2 Nov 2017 12:14:55 +0000 (+0200) Subject: Merge branch 'master' into 14a_rework3 X-Git-Tag: v3.1.0~133^2~5 X-Git-Url: http://cvs.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/commitdiff_plain/378d3406cae2ab5d6f8c43fd933134d5395c4ddb?hp=23207d748f65f97365a608f2a9abfc3ac5997413 Merge branch 'master' into 14a_rework3 --- diff --git a/CHANGELOG.md b/CHANGELOG.md index 044538c4..60caf413 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - `hf mf nested` Check keys after they have found (Merlok) - `hf mf chk` Move main cycle to arm (Merlok) - Changed proxmark command line parameter `flush` to `-f` or `-flush` (Merlok) +- Changed `hf 14a reader` to just reqest-anticilission-select sequence (Merlok) ### Fixed - Changed start sequence in Qt mode (fix: short commands hangs main Qt thread) (Merlok) @@ -32,6 +33,8 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Added to proxmark command line parameters `w` - wait 20s for serial port (Merlok) - Added to proxmark command line parameters `c` and `l` - execute command and lua script from command line (Merlok) - Added to proxmark ability to execute commands from stdin (pipe) (Merlok) +- Added `hf 14a info` and moved there functionality from `hf 14a reader` (Merlok) +- Added to `hf 14a info` detection of weak prng from Iceman1001 fork (Merlok) ## [3.0.1][2017-06-08] diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index c39b8a20..5a27e06b 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -1821,7 +1821,7 @@ int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, u } // PICC compilant with iso14443a-4 ---> (SAK & 0x20 != 0) - if( (sak & 0x20) == 0) return 2; + if( (sak & 0x20) == 0) return 2; if (!no_rats) { // Request for answer to select diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 86cfea2f..1ae63ada 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -220,8 +220,10 @@ int CmdHF14AInfo(const char *Cmd) PrintAndLog("ATQA : %02x %02x", card.atqa[1], card.atqa[0]); PrintAndLog(" SAK : %02x [%d]", card.sak, resp.arg[0]); + bool isMifareClassic = true; switch (card.sak) { case 0x00: + isMifareClassic = false; //***************************************test**************** // disconnect @@ -456,6 +458,19 @@ int CmdHF14AInfo(const char *Cmd) // try to see if card responses to "chinese magic backdoor" commands. mfCIdentify(); + if (isMifareClassic) { + switch(DetectClassicPrng()) { + case 0: + PrintAndLog("Prng detection: HARDEND (hardnested)"); + break; + case 1: + PrintAndLog("Prng detection: WEAK"); + break; + default: + PrintAndLog("Prng detection error."); + } + } + return select_status; } diff --git a/client/mifarehost.c b/client/mifarehost.c index fe1a8edb..67277b59 100644 --- a/client/mifarehost.c +++ b/client/mifarehost.c @@ -903,3 +903,72 @@ int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, return 0; } +/** validate_prng_nonce + * Determine if nonce is deterministic. ie: Suspectable to Darkside attack. + * returns + * true = weak prng + * false = hardend prng + */ +bool validate_prng_nonce(uint32_t nonce) { + uint16_t *dist = 0; + uint16_t x, i; + + dist = malloc(2 << 16); + if(!dist) + return -1; + + // init prng table: + for (x = i = 1; i; ++i) { + dist[(x & 0xff) << 8 | x >> 8] = i; + x = x >> 1 | (x ^ x >> 2 ^ x >> 3 ^ x >> 5) << 15; + } + + uint32_t res = (65535 - dist[nonce >> 16] + dist[nonce & 0xffff]) % 65535; + + free(dist); + return (res == 16); +} + +/* Detect Tag Prng, +* function performs a partial AUTH, where it tries to authenticate against block0, key A, but only collects tag nonce. +* the tag nonce is check to see if it has a predictable PRNG. +* @returns +* TRUE if tag uses WEAK prng (ie Now the NACK bug also needs to be present for Darkside attack) +* FALSE is tag uses HARDEND prng (ie hardnested attack possible, with known key) +*/ +int DetectClassicPrng(void){ + + UsbCommand resp, respA; + uint8_t cmd[] = {0x60, 0x00}; // MIFARE_AUTH_KEYA + uint32_t flags = ISO14A_CONNECT | ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_RATS; + + UsbCommand c = {CMD_READER_ISO_14443a, {flags, sizeof(cmd), 0}}; + memcpy(c.d.asBytes, cmd, sizeof(cmd)); + + clearCommandBuffer(); + SendCommand(&c); + if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + PrintAndLog("PRNG UID: Reply timeout."); + return -1; + } + + // if select tag failed. + if (resp.arg[0] == 0) { + PrintAndLog("PRNG error: selecting tag failed, can't detect prng."); + return -1; + } + + if (!WaitForResponseTimeout(CMD_ACK, &respA, 5000)) { + PrintAndLog("PRNG data: Reply timeout."); + return -1; + } + + // check respA + if (respA.arg[0] != 4) { + PrintAndLog("PRNG data error: Wrong length: %d", respA.arg[0]); + return -1; + } + + uint32_t nonce = bytes_to_num(respA.d.asBytes, respA.arg[0]); + return validate_prng_nonce(nonce); +} diff --git a/client/mifarehost.h b/client/mifarehost.h index 118d55cc..031dac1b 100644 --- a/client/mifarehost.h +++ b/client/mifarehost.h @@ -60,5 +60,6 @@ extern int saveTraceCard(void); extern int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int len); extern int mfCIdentify(); +extern int DetectClassicPrng(void); #endif diff --git a/common/crapto1/crapto1.c b/common/crapto1/crapto1.c index 9398a1f3..1edfca1b 100644 --- a/common/crapto1/crapto1.c +++ b/common/crapto1/crapto1.c @@ -426,7 +426,6 @@ int nonce_distance(uint32_t from, uint32_t to) return (65535 + dist[to >> 16] - dist[from >> 16]) % 65535; } - static uint32_t fastfwd[2][8] = { { 0, 0x4BC53, 0xECB1, 0x450E2, 0x25E29, 0x6E27A, 0x2B298, 0x60ECB}, { 0, 0x1D962, 0x4BC53, 0x56531, 0xECB1, 0x135D3, 0x450E2, 0x58980}};