X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/ea1c1ca6f88c4e9b1bcb75cd703f6be81df9b95c..966c111e8c8e45e624465502d0ee405ebda9a39c:/client/cmdanalyse.c diff --git a/client/cmdanalyse.c b/client/cmdanalyse.c index 32309c1c..a7004293 100644 --- a/client/cmdanalyse.c +++ b/client/cmdanalyse.c @@ -22,7 +22,7 @@ int usage_analyse_lcr(void) { PrintAndLog(" bytes to calc missing XOR in a LCR"); PrintAndLog(""); PrintAndLog("Samples:"); - PrintAndLog(" analyse lcr 04008064BA"); + PrintAndLog(" analyse lcr 04008064BA"); PrintAndLog("expected output: Target (BA) requires final LRC XOR byte value: 5A"); return 0; } @@ -30,14 +30,15 @@ int usage_analyse_checksum(void) { PrintAndLog("The bytes will be added with eachother and than limited with the applied mask"); PrintAndLog("Finally compute ones' complement of the least significant bytes"); PrintAndLog(""); - PrintAndLog("Usage: analyse chksum [h] b m "); + PrintAndLog("Usage: analyse chksum [h] [v] b m "); PrintAndLog("Options:"); PrintAndLog(" h This help"); + PrintAndLog(" v supress header"); PrintAndLog(" b bytes to calc missing XOR in a LCR"); PrintAndLog(" m bit mask to limit the outpuyt"); PrintAndLog(""); PrintAndLog("Samples:"); - PrintAndLog(" analyse chksum b 137AF00A0A0D m FF"); + PrintAndLog(" analyse chksum b 137AF00A0A0D m FF"); PrintAndLog("expected output: 0x61"); return 0; } @@ -50,7 +51,7 @@ int usage_analyse_crc(void){ PrintAndLog(" bytes to calc crc"); PrintAndLog(""); PrintAndLog("Samples:"); - PrintAndLog(" analyse crc 137AF00A0A0D"); + PrintAndLog(" analyse crc 137AF00A0A0D"); return 0; } int usage_analyse_hid(void){ @@ -64,7 +65,19 @@ int usage_analyse_hid(void){ PrintAndLog(" input bytes"); PrintAndLog(""); PrintAndLog("Samples:"); - PrintAndLog(" analyse hid r 0123456789abcdef"); + PrintAndLog(" analyse hid r 0123456789abcdef"); + return 0; +} +int usage_analyse_nuid(void){ + PrintAndLog("Generate 4byte NUID from 7byte UID"); + PrintAndLog(""); + PrintAndLog("Usage: analyse hid [h] "); + PrintAndLog("Options:"); + PrintAndLog(" h This help"); + PrintAndLog(" input bytes (14 hexsymbols)"); + PrintAndLog(""); + PrintAndLog("Samples:"); + PrintAndLog(" analyse nuid 11223344556677"); return 0; } @@ -75,7 +88,7 @@ static uint8_t calculateLRC( uint8_t* bytes, uint8_t len) { return LRC; } -static uint8_t calcSumCrumbAdd( uint8_t* bytes, uint8_t len, uint32_t mask) { +static uint16_t calcSumCrumbAdd( uint8_t* bytes, uint8_t len, uint32_t mask) { uint8_t sum = 0; for (uint8_t i = 0; i < len; i++) { sum += CRUMB(bytes[i], 0); @@ -86,10 +99,10 @@ static uint8_t calcSumCrumbAdd( uint8_t* bytes, uint8_t len, uint32_t mask) { sum &= mask; return sum; } -static uint8_t calcSumCrumbAddOnes( uint8_t* bytes, uint8_t len, uint32_t mask) { - return ~calcSumCrumbAdd(bytes, len, mask); +static uint16_t calcSumCrumbAddOnes( uint8_t* bytes, uint8_t len, uint32_t mask) { + return (~calcSumCrumbAdd(bytes, len, mask) & mask); } -static uint8_t calcSumNibbleAdd( uint8_t* bytes, uint8_t len, uint32_t mask) { +static uint16_t calcSumNibbleAdd( uint8_t* bytes, uint8_t len, uint32_t mask) { uint8_t sum = 0; for (uint8_t i = 0; i < len; i++) { sum += NIBBLE_LOW(bytes[i]); @@ -98,27 +111,37 @@ static uint8_t calcSumNibbleAdd( uint8_t* bytes, uint8_t len, uint32_t mask) { sum &= mask; return sum; } -static uint8_t calcSumNibbleAddOnes( uint8_t* bytes, uint8_t len, uint32_t mask){ - return ~calcSumNibbleAdd(bytes, len, mask); +static uint16_t calcSumNibbleAddOnes( uint8_t* bytes, uint8_t len, uint32_t mask){ + return (~calcSumNibbleAdd(bytes, len, mask) & mask); +} +static uint16_t calcSumCrumbXor( uint8_t* bytes, uint8_t len, uint32_t mask) { + uint8_t sum = 0; + for (uint8_t i = 0; i < len; i++) { + sum ^= CRUMB(bytes[i], 0); + sum ^= CRUMB(bytes[i], 2); + sum ^= CRUMB(bytes[i], 4); + sum ^= CRUMB(bytes[i], 6); + } + sum &= mask; + return sum; } -static uint8_t calcSumNibbleXor( uint8_t* bytes, uint8_t len, uint32_t mask) { +static uint16_t calcSumNibbleXor( uint8_t* bytes, uint8_t len, uint32_t mask) { uint8_t sum = 0; for (uint8_t i = 0; i < len; i++) { sum ^= NIBBLE_LOW(bytes[i]); sum ^= NIBBLE_HIGH(bytes[i]); } - sum &= mask; + sum &= mask; return sum; } -static uint8_t calcSumByteXor( uint8_t* bytes, uint8_t len, uint32_t mask) { +static uint16_t calcSumByteXor( uint8_t* bytes, uint8_t len, uint32_t mask) { uint8_t sum = 0; for (uint8_t i = 0; i < len; i++) sum ^= bytes[i]; sum &= mask; return sum; } - -static uint8_t calcSumByteAdd( uint8_t* bytes, uint8_t len, uint32_t mask) { +static uint16_t calcSumByteAdd( uint8_t* bytes, uint8_t len, uint32_t mask) { uint8_t sum = 0; for (uint8_t i = 0; i < len; i++) sum += bytes[i]; @@ -126,23 +149,21 @@ static uint8_t calcSumByteAdd( uint8_t* bytes, uint8_t len, uint32_t mask) { return sum; } // Ones complement -static uint8_t calcSumByteAddOnes( uint8_t* bytes, uint8_t len, uint32_t mask) { - return ~calcSumByteAdd(bytes, len, mask); +static uint16_t calcSumByteAddOnes( uint8_t* bytes, uint8_t len, uint32_t mask) { + return (~calcSumByteAdd(bytes, len, mask) & mask); } - - -static uint8_t calcSumByteSub( uint8_t* bytes, uint8_t len, uint32_t mask) { +static uint16_t calcSumByteSub( uint8_t* bytes, uint8_t len, uint32_t mask) { uint8_t sum = 0; for (uint8_t i = 0; i < len; i++) sum -= bytes[i]; sum &= mask; return sum; } -static uint8_t calcSumByteSubOnes( uint8_t* bytes, uint8_t len, uint32_t mask){ - return ~calcSumByteSub(bytes, len, mask); +static uint16_t calcSumByteSubOnes( uint8_t* bytes, uint8_t len, uint32_t mask){ + return (~calcSumByteSub(bytes, len, mask) & mask); } -static uint8_t calcSumNibbleSub( uint8_t* bytes, uint8_t len, uint32_t mask) { +static uint16_t calcSumNibbleSub( uint8_t* bytes, uint8_t len, uint32_t mask) { uint8_t sum = 0; for (uint8_t i = 0; i < len; i++) { sum -= NIBBLE_LOW(bytes[i]); @@ -151,8 +172,34 @@ static uint8_t calcSumNibbleSub( uint8_t* bytes, uint8_t len, uint32_t mask) { sum &= mask; return sum; } -static uint8_t calcSumNibbleSubOnes( uint8_t* bytes, uint8_t len, uint32_t mask) { - return ~calcSumNibbleSub(bytes, len, mask); +static uint16_t calcSumNibbleSubOnes( uint8_t* bytes, uint8_t len, uint32_t mask) { + return (~calcSumNibbleSub(bytes, len, mask) & mask); +} + +// BSD shift checksum 8bit version +static uint16_t calcBSDchecksum8( uint8_t* bytes, uint8_t len, uint32_t mask){ + uint16_t sum = 0; + for(uint8_t i = 0; i < len; i++){ + sum = ((sum & 0xFF) >> 1) | ((sum & 0x1) << 7); // rotate accumulator + sum += bytes[i]; // add next byte + sum &= 0xFF; // + } + sum &= mask; + return sum; +} +// BSD shift checksum 4bit version +static uint16_t calcBSDchecksum4( uint8_t* bytes, uint8_t len, uint32_t mask){ + uint16_t sum = 0; + for(uint8_t i = 0; i < len; i++){ + sum = ((sum & 0xF) >> 1) | ((sum & 0x1) << 3); // rotate accumulator + sum += NIBBLE_HIGH(bytes[i]); // add high nibble + sum &= 0xF; // + sum = ((sum & 0xF) >> 1) | ((sum & 0x1) << 3); // rotate accumulator + sum += NIBBLE_LOW(bytes[i]); // add low nibble + sum &= 0xF; // + } + sum &= mask; + return sum; } // measuring LFSR maximum length @@ -248,8 +295,9 @@ int CmdAnalyseCHKSUM(const char *Cmd){ uint8_t data[50]; uint8_t cmdp = 0; - uint32_t mask = 0xFF; + uint32_t mask = 0xFFFF; bool errors = false; + bool useHeader = false; int len = 0; memset(data, 0x0, sizeof(data)); @@ -267,6 +315,11 @@ int CmdAnalyseCHKSUM(const char *Cmd){ mask = param_get32ex(Cmd, cmdp+1, 0, 16); cmdp += 2; break; + case 'v': + case 'V': + useHeader = true; + cmdp++; + break; case 'h': case 'H': return usage_analyse_checksum(); @@ -280,25 +333,28 @@ int CmdAnalyseCHKSUM(const char *Cmd){ //Validations if(errors) return usage_analyse_checksum(); - PrintAndLog("\nByte Add | 0x%X", calcSumByteAdd(data, len, mask)); - PrintAndLog("Nibble Add | 0x%X", calcSumNibbleAdd(data, len, mask)); - PrintAndLog("Crumb Add | 0x%X", calcSumCrumbAdd(data, len, mask)); - - PrintAndLog("\nByte Subtract | 0x%X", calcSumByteSub(data, len, mask)); - PrintAndLog("Nibble Subtract | 0x%X", calcSumNibbleSub(data, len, mask)); - - PrintAndLog("\nCHECKSUM - One's complement"); - PrintAndLog("Byte Add | 0x%X", calcSumByteAddOnes(data, len, mask)); - PrintAndLog("Nibble Add | 0x%X", calcSumNibbleAddOnes(data, len, mask)); - PrintAndLog("Crumb Add | 0x%X", calcSumCrumbAddOnes(data, len, mask)); - - PrintAndLog("Byte Subtract | 0x%X", calcSumByteSubOnes(data, len, mask)); - PrintAndLog("Nibble Subtract | 0x%X", calcSumNibbleSubOnes(data, len, mask)); - - PrintAndLog("\nXOR"); - PrintAndLog("Byte Xor | 0x%X", calcSumByteXor(data, len, mask)); - PrintAndLog("Nibble Xor | 0x%X", calcSumNibbleXor(data, len, mask)); - + if (useHeader) { + PrintAndLog(" add | sub | add 1's compl | sub 1's compl | xor"); + PrintAndLog("byte nibble crumb | byte nibble | byte nibble cumb | byte nibble | byte nibble cumb | BSD |"); + PrintAndLog("------------------+-------------+------------------+-----------------+--------------------"); + } + PrintAndLog("0x%X 0x%X 0x%X | 0x%X 0x%X | 0x%X 0x%X 0x%X | 0x%X 0x%X | 0x%X 0x%X 0x%X | 0x%X 0x%X |\n", + calcSumByteAdd(data, len, mask) + , calcSumNibbleAdd(data, len, mask) + , calcSumCrumbAdd(data, len, mask) + , calcSumByteSub(data, len, mask) + , calcSumNibbleSub(data, len, mask) + , calcSumByteAddOnes(data, len, mask) + , calcSumNibbleAddOnes(data, len, mask) + , calcSumCrumbAddOnes(data, len, mask) + , calcSumByteSubOnes(data, len, mask) + , calcSumNibbleSubOnes(data, len, mask) + , calcSumByteXor(data, len, mask) + , calcSumNibbleXor(data, len, mask) + , calcSumCrumbXor(data, len, mask) + , calcBSDchecksum8(data, len, mask) + , calcBSDchecksum4(data, len, mask) + ); return 0; } @@ -477,6 +533,53 @@ int CmdAnalyseHid(const char *Cmd){ return 0; } +void generate4bNUID(uint8_t *uid, uint8_t *nuid){ + uint16_t crc; + uint8_t first, second; + + ComputeCrc14443(CRC_14443_A, uid, 3, &first, &second); + nuid[0] |= (second & 0xE0) | 0xF; + nuid[1] = first; + + crc = first; + crc |= second << 8; + + UpdateCrc14443(uid[3], &crc); + UpdateCrc14443(uid[4], &crc); + UpdateCrc14443(uid[5], &crc); + UpdateCrc14443(uid[6], &crc); + + nuid[2] = (crc >> 8) & 0xFF ; + nuid[3] = crc & 0xFF; +} + +int CmdAnalyseNuid(const char *Cmd){ + uint8_t nuid[4] = {0}; + uint8_t uid[7] = {0}; + int len = 0; + char cmdp = param_getchar(Cmd, 0); + if (strlen(Cmd) == 0|| cmdp == 'h' || cmdp == 'H') return usage_analyse_nuid(); + + /* selftest UID 040D681AB52281 -> NUID 8F430FEF */ + if (cmdp == 't' || cmdp == 'T') { + memcpy(uid, "\x04\x0d\x68\x1a\xb5\x22\x81", 7); + generate4bNUID(uid, nuid); + if ( 0 == memcmp(nuid, "\x8f\x43\x0f\xef", 4)) + printf("Selftest OK\n"); + else + printf("Selftest Failed\n"); + return 0; + } + + param_gethex_ex(Cmd, 0, uid, &len); + if ( len%2 || len != 14) return usage_analyse_nuid(); + + generate4bNUID(uid, nuid); + + printf("UID | %s \n", sprint_hex(uid, 7)); + printf("NUID | %s \n", sprint_hex(nuid, 4)); + return 0; +} static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, {"lcr", CmdAnalyseLCR, 1, "Generate final byte for XOR LRC"}, @@ -487,6 +590,7 @@ static command_t CommandTable[] = { {"lfsr", CmdAnalyseLfsr, 1, "LFSR tests"}, {"a", CmdAnalyseA, 1, "num bits test"}, {"hid", CmdAnalyseHid, 1, "Permute function from 'heart of darkness' paper"}, + {"nuid", CmdAnalyseNuid, 1, "create NUID from 7byte UID"}, {NULL, NULL, 0, NULL} };