]> git.zerfleddert.de Git - proxmark3-svn/commitdiff
Merge pull request #114 from pwpiwi/iso14443b_fix
authorpwpiwi <pwpiwi@users.noreply.github.com>
Tue, 23 Jun 2015 05:14:52 +0000 (07:14 +0200)
committerpwpiwi <pwpiwi@users.noreply.github.com>
Tue, 23 Jun 2015 05:14:52 +0000 (07:14 +0200)
fixing iso14443b (issue #103): fix bug introduced during Bigbuf rework

13 files changed:
armsrc/aes.c
armsrc/optimized_cipher.c
client/cmddata.c
client/cmddata.h
client/cmdhfmfu.c
client/cmdhfmfu.h
client/cmdlf.c
client/scripts/didump.lua [new file with mode: 0644]
common/crc16.c
common/crc16.h
common/lfdemod.c
common/lfdemod.h
common/protocols.c

index 3df006bb355f2b0f7db494b36f98c8fd53355868..a199d04b7dc8d48bacbf446de619406385320159 100644 (file)
@@ -1,4 +1,3 @@
-#include "stdio.h"
 #include "aes.h"
 
 static const unsigned int Te0[256] = {
@@ -1138,6 +1137,9 @@ int AesDecrypt(AesCtx *pCtx, unsigned char *pCipher, unsigned char *pData, unsig
 //////////////////////////////////////////////////////////////////////////////
 
 #ifndef EMBEDDED
+
+#include <stdio.h>
+
 int main()
 {
     AesCtx ctx;
index 444b93d09f688db68b71d152745c3a92f84c6b43..2356262114da1123395e534fab0e30da579743b9 100644 (file)
@@ -61,7 +61,6 @@
 **/
 
 #include "optimized_cipher.h"
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stdbool.h>
index 76552351846713d433309c0ba9ce2c0de31617dc..309044e10d48cefe327f028d83c4d13bca9e170c 100644 (file)
@@ -23,6 +23,7 @@
 #include "lfdemod.h"
 #include "usb_cmd.h"
 #include "crc.h"
+#include "crc16.h"
 
 uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN];
 uint8_t g_debugMode;
@@ -343,8 +344,8 @@ int ASKDemod(const char *Cmd, bool verbose, bool emSearch, uint8_t askType)
        setDemodBuf(BitStream,BitLen,0);
        if (verbose || g_debugMode){
                if (errCnt>0) PrintAndLog("# Errors during Demoding (shown as 7 in bit stream): %d",errCnt);
-               if (askType) PrintAndLog("ASK/Manchester decoded bitstream:");
-               else PrintAndLog("ASK/Raw decoded bitstream:");
+               if (askType) PrintAndLog("ASK/Manchester - Clock: %d - Decoded bitstream:",clk);
+               else PrintAndLog("ASK/Raw - Clock: %d - Decoded bitstream:",clk);
                // Now output the bitstream to the scrollback by line of 16 bits
                printDemodBuff();
                
@@ -497,22 +498,20 @@ int CmdBiphaseDecodeRaw(const char *Cmd)
 int ASKbiphaseDemod(const char *Cmd, bool verbose)
 {
        //ask raw demod GraphBuffer first
-       int offset=0, clk=0, invert=0, maxErr=0, ans=0;
-       ans = sscanf(Cmd, "%i %i %i %i", &offset, &clk, &invert, &maxErr);
-       if (ans>0)
-               ans = ASKDemod(Cmd+1, FALSE, FALSE, 0);
-       else
-               ans = ASKDemod(Cmd, FALSE, FALSE, 0);
-       if (!ans) {
-               if (g_debugMode || verbose) PrintAndLog("Error AskDemod: %d", ans);
-               return 0;
-       }
+       int offset=0, clk=0, invert=0, maxErr=0;
+       sscanf(Cmd, "%i %i %i %i", &offset, &clk, &invert, &maxErr);
+
+       uint8_t BitStream[MAX_DEMOD_BUF_LEN];     
+       size_t size = getFromGraphBuf(BitStream);         
+       //invert here inverts the ask raw demoded bits which has no effect on the demod, but we need the pointer
+       int errCnt = askdemod(BitStream, &size, &clk, &invert, maxErr, 0, 0);  
+       if ( errCnt < 0 || errCnt > maxErr ) {   
+               if (g_debugMode) PrintAndLog("DEBUG: no data or error found %d, clock: %d", errCnt, clk);  
+                       return 0;  
+       } 
 
-       //attempt to Biphase decode DemodBuffer
-       size_t size = DemodBufferLen;
-       uint8_t BitStream[MAX_DEMOD_BUF_LEN];
-       memcpy(BitStream, DemodBuffer, DemodBufferLen); 
-       int errCnt = BiphaseRawDecode(BitStream, &size, offset, 0);
+       //attempt to Biphase decode BitStream
+       errCnt = BiphaseRawDecode(BitStream, &size, offset, invert);
        if (errCnt < 0){
                if (g_debugMode || verbose) PrintAndLog("Error BiphaseRawDecode: %d", errCnt);
                return 0;
@@ -524,7 +523,7 @@ int ASKbiphaseDemod(const char *Cmd, bool verbose)
        //success set DemodBuffer and return
        setDemodBuf(BitStream, size, 0);
        if (g_debugMode || verbose){
-               PrintAndLog("Biphase Decoded using offset: %d - # errors:%d - data:",offset,errCnt);
+               PrintAndLog("Biphase Decoded using offset: %d - clock: %d - # errors:%d - data:",offset,clk,errCnt);
                printDemodBuff();
        }
        return 1;
@@ -1457,6 +1456,83 @@ int CmdFSKdemodPyramid(const char *Cmd)
        return 1;
 }
 
+// FDX-B ISO11784/85 demod  (aka animal tag)  BIPHASE, inverted, rf/32,  with preamble of 00000000001 (128bits)
+// 8 databits + 1 parity (1)
+// CIITT 16 chksum
+// NATIONAL CODE, ICAR database
+// COUNTRY CODE (ISO3166) or http://cms.abvma.ca/uploads/ManufacturersISOsandCountryCodes.pdf
+// FLAG (animal/non-animal)
+int CmdFDXBdemodBI(const char *Cmd){
+
+       int invert = 1;
+       int clk = 32;           
+       int errCnt = 0;
+       int maxErr = 0;
+       uint8_t BitStream[MAX_DEMOD_BUF_LEN];   
+       size_t size = getFromGraphBuf(BitStream);       
+       
+       errCnt = askdemod(BitStream, &size, &clk, &invert, maxErr, 0, 0);
+       if ( errCnt < 0 || errCnt > maxErr ) { 
+               if (g_debugMode) PrintAndLog("DEBUG: no data or error found %d, clock: %d", errCnt, clk);
+               return 0;
+       }
+
+       errCnt = BiphaseRawDecode(BitStream, &size, maxErr, 1);
+       if (errCnt < 0 || errCnt > maxErr ) {
+               if (g_debugMode) PrintAndLog("Error BiphaseRawDecode: %d", errCnt);
+               return 0;
+       } 
+
+       int preambleIndex = FDXBdemodBI(BitStream, &size);
+       if (preambleIndex < 0){
+               if (g_debugMode) PrintAndLog("Error FDXBDemod , no startmarker found :: %d",preambleIndex);
+               return 0;
+       }
+
+       setDemodBuf(BitStream, 128, preambleIndex);
+
+       // remove but don't verify parity. (pType = 2)
+       size = removeParity(BitStream, preambleIndex + 11, 9, 2, 117);
+       if ( size <= 103 ) {
+               if (g_debugMode) PrintAndLog("Error removeParity:: %d", size);
+               return 0;
+       }
+       if (g_debugMode) {
+               char *bin = sprint_bin_break(BitStream,size,16);
+               PrintAndLog("DEBUG BinStream:\n%s",bin);
+       }
+       PrintAndLog("\nFDX-B / ISO 11784/5 Animal Tag ID Found:");
+       if (g_debugMode) PrintAndLog("Start marker %d;   Size %d", preambleIndex, size);
+
+       //got a good demod
+       uint64_t NationalCode = ((uint64_t)(bytebits_to_byteLSBF(BitStream+32,6)) << 32) | bytebits_to_byteLSBF(BitStream,32);
+       uint32_t countryCode = bytebits_to_byteLSBF(BitStream+38,10);
+       uint8_t dataBlockBit = BitStream[48];
+       uint32_t reservedCode = bytebits_to_byteLSBF(BitStream+49,14);
+       uint8_t animalBit = BitStream[63];
+       uint32_t crc16 = bytebits_to_byteLSBF(BitStream+64,16);
+       uint32_t extended = bytebits_to_byteLSBF(BitStream+80,24);
+
+       uint64_t rawid = ((uint64_t)bytebits_to_byte(BitStream,32)<<32) | bytebits_to_byte(BitStream+32,32);
+       uint8_t raw[8];
+       num_to_bytes(rawid, 8, raw);
+
+       if (g_debugMode) PrintAndLog("Raw ID Hex: %s", sprint_hex(raw,8));
+
+       uint16_t calcCrc = crc16_ccitt_kermit(raw, 8);
+       PrintAndLog("Animal ID:     %04u-%012llu", countryCode, NationalCode);
+       PrintAndLog("National Code: %012llu", NationalCode);
+       PrintAndLog("CountryCode:   %04u", countryCode);
+       PrintAndLog("Extended Data: %s", dataBlockBit ? "True" : "False");
+       PrintAndLog("reserved Code: %u", reservedCode);
+       PrintAndLog("Animal Tag:    %s", animalBit ? "True" : "False");
+       PrintAndLog("CRC:           0x%04X - [%04X] - %s", crc16, calcCrc, (calcCrc == crc16) ? "Passed" : "Failed");
+       PrintAndLog("Extended:      0x%X\n", extended);
+       
+       return 1;
+}
+
+
 //by marshmellow
 //attempt to psk1 demod graph buffer
 int PSKDemod(const char *Cmd, bool verbose)
@@ -2201,6 +2277,7 @@ static command_t CommandTable[] =
        {"buffclear",       CmdBuffClear,       1, "Clear sample buffer and graph window"},
        {"dec",             CmdDec,             1, "Decimate samples"},
        {"detectclock",     CmdDetectClockRate, 1, "[modulation] Detect clock rate of wave in GraphBuffer (options: 'a','f','n','p' for ask, fsk, nrz, psk respectively)"},
+       {"fdxbdemod",       CmdFDXBdemodBI    , 1, "Demodulate a FDX-B ISO11784/85 Biphase tag from GraphBuffer"},
        {"fskawiddemod",    CmdFSKdemodAWID,    1, "Demodulate an AWID FSK tag from GraphBuffer"},
        //{"fskfcdetect",   CmdFSKfcDetect,     1, "Try to detect the Field Clock of an FSK wave"},
        {"fskhiddemod",     CmdFSKdemodHID,     1, "Demodulate a HID FSK tag from GraphBuffer"},
index c62307368d6ef3965a3d7dad3ae2842b9afc36d5..fcc51a6bee079068127950e46a2fde9dd9edf3bf 100644 (file)
@@ -27,6 +27,7 @@ int CmdBitsamples(const char *Cmd);
 int CmdBuffClear(const char *Cmd);
 int CmdDec(const char *Cmd);
 int CmdDetectClockRate(const char *Cmd);
+int CmdFDXBdemodBI(const char *Cmd);
 int CmdFSKdemodAWID(const char *Cmd);
 int CmdFSKdemodHID(const char *Cmd);
 int CmdFSKdemodIO(const char *Cmd);
index 5d211558e2f3a1049de46bbbfa62dc5c22980804..48f549ba8334f4ecbd0fb97180c120ace6a73993 100644 (file)
 #include "protocols.h"
 #include "data.h"
 
-#define MAX_UL_BLOCKS     0x0f
-#define MAX_ULC_BLOCKS    0x2b
-#define MAX_ULEV1a_BLOCKS 0x13
-#define MAX_ULEV1b_BLOCKS 0x28
-#define MAX_NTAG_203      0x29
-#define MAX_NTAG_210      0x13
-#define MAX_NTAG_212      0x28
-#define MAX_NTAG_213      0x2c
-#define MAX_NTAG_215      0x86
-#define MAX_NTAG_216      0xe6
+#define MAX_UL_BLOCKS      0x0f
+#define MAX_ULC_BLOCKS     0x2b
+#define MAX_ULEV1a_BLOCKS  0x13
+#define MAX_ULEV1b_BLOCKS  0x28
+#define MAX_NTAG_203       0x29
+#define MAX_NTAG_210       0x13
+#define MAX_NTAG_212       0x28
+#define MAX_NTAG_213       0x2c
+#define MAX_NTAG_215       0x86
+#define MAX_NTAG_216       0xe6
+#define MAX_MY_D_NFC       0xff
+#define MAX_MY_D_MOVE      0x25
+#define MAX_MY_D_MOVE_LEAN 0x0f
 
 #define KEYS_3DES_COUNT 7
 uint8_t default_3des_keys[KEYS_3DES_COUNT][16] = {
@@ -54,17 +57,18 @@ uint8_t default_pwd_pack[KEYS_PWD_COUNT][4] = {
        {0x32,0x0C,0x16,0x17}, // PACK 0x80,0x80 -- AMiiboo (sniffed) 
 };
 
-#define MAX_UL_TYPES 16
+#define MAX_UL_TYPES 17
 uint16_t UL_TYPES_ARRAY[MAX_UL_TYPES] = {UNKNOWN, UL, UL_C, UL_EV1_48, UL_EV1_128, NTAG, NTAG_203,
-           NTAG_210, NTAG_212, NTAG_213, NTAG_215, NTAG_216, MY_D, MY_D_NFC, MY_D_MOVE, MY_D_MOVE_NFC};
+           NTAG_210, NTAG_212, NTAG_213, NTAG_215, NTAG_216, MY_D, MY_D_NFC, MY_D_MOVE, MY_D_MOVE_NFC, MY_D_MOVE_LEAN};
 
 uint8_t UL_MEMORY_ARRAY[MAX_UL_TYPES] = {MAX_UL_BLOCKS, MAX_UL_BLOCKS, MAX_ULC_BLOCKS, MAX_ULEV1a_BLOCKS,
            MAX_ULEV1b_BLOCKS, MAX_NTAG_203, MAX_NTAG_203, MAX_NTAG_210, MAX_NTAG_212, MAX_NTAG_213,
-           MAX_NTAG_215, MAX_NTAG_216, MAX_UL_BLOCKS, MAX_UL_BLOCKS, MAX_UL_BLOCKS, MAX_UL_BLOCKS};
+           MAX_NTAG_215, MAX_NTAG_216, MAX_UL_BLOCKS, MAX_MY_D_NFC, MAX_MY_D_MOVE, MAX_MY_D_MOVE, MAX_MY_D_MOVE_LEAN};
 
 
 static int CmdHelp(const char *Cmd);
 
+// get version nxp product type 
 char *getProductTypeStr( uint8_t id){
 
        static char buf[20];
@@ -285,12 +289,12 @@ static int ul_print_default( uint8_t *data){
 
        PrintAndLog("       UID : %s ", sprint_hex(uid, 7));
        PrintAndLog("    UID[0] : %02X, %s",  uid[0], getTagInfo(uid[0]) );
-       if ( uid[0] == 0x05 ) {
+       if ( uid[0] == 0x05 && ((uid[1] & 0xf0) >> 4) == 2 ) { // is infineon and 66RxxP
                uint8_t chip = (data[8] & 0xC7); // 11000111  mask, bit 3,4,5 RFU
                switch (chip){
-                       case 0xc2: PrintAndLog("   IC type : SLE 66R04P"); break;
-                       case 0xc4: PrintAndLog("   IC type : SLE 66R16P"); break;
-                       case 0xc6: PrintAndLog("   IC type : SLE 66R32P"); break;
+                       case 0xc2: PrintAndLog("   IC type : SLE 66R04P 770 Bytes"); break; //77 pages
+                       case 0xc4: PrintAndLog("   IC type : SLE 66R16P 2560 Bytes"); break; //256 pages
+                       case 0xc6: PrintAndLog("   IC type : SLE 66R32P 5120 Bytes"); break; //512 pages /2 sectors
                }
        }
        // CT (cascade tag byte) 0x88 xor SN0 xor SN1 xor SN2 
@@ -376,13 +380,15 @@ int ul_print_type(uint32_t tagtype, uint8_t spaces){
        else if ( tagtype & NTAG_I2C_2K )       
                PrintAndLog("%sTYPE : NTAG I%sC 1904bytes (NT3H1201FHK)", spacer, "\xFD");
        else if ( tagtype & MY_D )
-               PrintAndLog("%sTYPE : INFINEON my-d\x99", spacer);
+               PrintAndLog("%sTYPE : INFINEON my-d\x99 (SLE 66RxxS)", spacer);
        else if ( tagtype & MY_D_NFC )
-               PrintAndLog("%sTYPE : INFINEON my-d\x99 NFC", spacer);
+               PrintAndLog("%sTYPE : INFINEON my-d\x99 NFC (SLE 66RxxP)", spacer);
        else if ( tagtype & MY_D_MOVE )
-               PrintAndLog("%sTYPE : INFINEON my-d\x99 move", spacer);
+               PrintAndLog("%sTYPE : INFINEON my-d\x99 move (SLE 66R01P)", spacer);
        else if ( tagtype & MY_D_MOVE_NFC )
-               PrintAndLog("%sTYPE : INFINEON my-d\x99 move NFC", spacer);
+               PrintAndLog("%sTYPE : INFINEON my-d\x99 move NFC (SLE 66R01P)", spacer);
+       else if ( tagtype & MY_D_MOVE_LEAN )
+               PrintAndLog("%sTYPE : INFINEON my-d\x99 move lean (SLE 66R01L)", spacer);
        else
                PrintAndLog("%sTYPE : Unknown %06x", spacer, tagtype);
        return 0;
@@ -617,12 +623,15 @@ uint32_t GetHF14AMfU_Type(void){
                        }
                }
        } else {
+               ul_switch_off_field();
                // Infinition MY-D tests   Exam high nibble 
                uint8_t nib = (card.uid[1] & 0xf0) >> 4;
                switch ( nib ){
-                       case 1: tagtype =  MY_D; break;
-                       case 2: tagtype = (MY_D | MY_D_NFC); break; //notice: we can not currently distinguish between these two
-                       case 3: tagtype = (MY_D_MOVE | MY_D_MOVE_NFC); break; //notice: we can not currently distinguish between these two
+                       // case 0: tagtype =  SLE66R35E7; break; //or SLE 66R35E7 - mifare compat... should have different sak/atqa for mf 1k
+                       case 1: tagtype =  MY_D; break; //or SLE 66RxxS ... up to 512 pages of 8 user bytes...
+                       case 2: tagtype = (MY_D_NFC); break; //or SLE 66RxxP ... up to 512 pages of 8 user bytes... (or in nfc mode FF pages of 4 bytes)
+                       case 3: tagtype = (MY_D_MOVE | MY_D_MOVE_NFC); break; //or SLE 66R01P // 38 pages of 4 bytes //notice: we can not currently distinguish between these two
+                       case 7: tagtype =  MY_D_MOVE_LEAN; break; //or SLE 66R01L  // 16 pages of 4 bytes
                }
        }
 
index 4ec48ff9dfbcb07c9d7768c3a589c20f2a8b7163..132e4f9086b1431711cdff020b33dbf65b6c6fb9 100644 (file)
@@ -42,9 +42,10 @@ typedef enum TAGTYPE_UL {
        MY_D_NFC      = 0x001000,
        MY_D_MOVE     = 0x002000,
        MY_D_MOVE_NFC = 0x004000,
-       NTAG_I2C_1K   = 0x008000,
-       NTAG_I2C_2K   = 0x010000,
-       MAGIC         = 0x020000,
+       MY_D_MOVE_LEAN= 0x008000,
+       NTAG_I2C_1K   = 0x010000,
+       NTAG_I2C_2K   = 0x020000,
+       MAGIC         = 0x040000,
        UL_MAGIC      = UL | MAGIC,
        UL_C_MAGIC    = UL_C | MAGIC,
        UL_ERROR      = 0xFFFFFF,
index dfbbe992a76a6a3bdeadb0d01becdc2cb7a051e5..edf029325ddbe8e353197cdbc667681e14acadc2 100644 (file)
@@ -1072,6 +1072,12 @@ int CmdLFfind(const char *Cmd)
                return 1;
        }
 
+       ans=CmdFDXBdemodBI("");
+       if (ans>0) {
+               PrintAndLog("\nValid FDX-B ID Found!");
+               return 1;
+       }
+
        ans=EM4x50Read("", false);
        if (ans>0) {
                PrintAndLog("\nValid EM4x50 ID Found!");
diff --git a/client/scripts/didump.lua b/client/scripts/didump.lua
new file mode 100644 (file)
index 0000000..2386d42
--- /dev/null
@@ -0,0 +1,473 @@
+local cmds = require('commands')
+local getopt = require('getopt')
+local utils = require('utils')
+local lib14a = require('read14a')
+
+example =[[
+       script run didump
+       script run didump -k aabbccddeeff
+]]
+author = "Iceman"
+usage = "script run didump -k <key> "
+desc = [[
+This is a script to dump and decrypt the data of a specific type of Mifare Mini token.
+
+Arguments:
+       -h             : this help
+       -k <key>       : Mifare Key A.
+]]
+
+local band=bit32.band
+local bor=bit32.bor
+local bnot=bit32.bnot
+local bxor=bit32.bxor
+local lshift=bit32.lshift
+local rshift=bit32.rshift
+
+local FOO = 'AF62D2EC0491968CC52A1A7165F865FE'
+local BAR = '286329204469736E65792032303133'
+local RANDOM = FOO..BAR
+local outputTemplate = os.date("toydump_%Y-%m-%d_%H%M%S");
+local TIMEOUT = 2000
+local DEBUG = false
+local numBlocks = 20
+local numSectors = 5
+local CHECKSUM_OFFSET = 12; -- +1???
+--- 
+-- A debug printout-function
+function dbg(args)
+       if DEBUG then
+               print("###", args)
+       end
+end 
+--- 
+-- This is only meant to be used when errors occur
+function oops(err)
+       print("ERROR: ",err)
+       core.clearCommandBuffer()
+end
+--- 
+-- Usage help
+function help()
+       print(desc)
+       print("Example usage")
+       print(example)
+end
+---
+-- Get checksum,
+-- called: data is string (32 hex digits)
+-- returns: number
+local function getChecksum(data)
+       local chksum = data:sub(25,32)
+       return tonumber(chksum,16)
+end
+---
+-- calculate checksum
+-- called: data is bytes  (24 hex digits)
+-- returns: number
+local function calculateChecksum(data)
+
+       -- Generate table
+       local _tbl = {}
+_tbl[0] = { 0x0 }
+_tbl[1] = { 0x77073096 }
+_tbl[2] = { 0xEE0E612C }
+_tbl[3] = { 0x990951BA }
+_tbl[4] = { 0x76DC419 }
+_tbl[5] = { 0x706AF48F }
+_tbl[6] = { 0xE963A535 }
+_tbl[7] = { 0x9E6495A3 }
+_tbl[8] = { 0xEDB8832 }
+_tbl[9] = { 0x79DCB8A4 }
+_tbl[10] = { 0xE0D5E91E }
+_tbl[11] = { 0x97D2D988 }
+_tbl[12] = { 0x9B64C2B }
+_tbl[13] = { 0x7EB17CBD }
+_tbl[14] = { 0xE7B82D07 }
+_tbl[15] = { 0x90BF1D91 }
+_tbl[16] = { 0x1DB71064 }
+_tbl[17] = { 0x6AB020F2 }
+_tbl[18] = { 0xF3B97148 }
+_tbl[19] = { 0x84BE41DE }
+_tbl[20] = { 0x1ADAD47D }
+_tbl[21] = { 0x6DDDE4EB }
+_tbl[22] = { 0xF4D4B551 }
+_tbl[23] = { 0x83D385C7 }
+_tbl[24] = { 0x136C9856 }
+_tbl[25] = { 0x646BA8C0 }
+_tbl[26] = { 0xFD62F97A }
+_tbl[27] = { 0x8A65C9EC }
+_tbl[28] = { 0x14015C4F }
+_tbl[29] = { 0x63066CD9 }
+_tbl[30] = { 0xFA0F3D63 }
+_tbl[31] = { 0x8D080DF5 }
+_tbl[32] = { 0x3B6E20C8 }
+_tbl[33] = { 0x4C69105E }
+_tbl[34] = { 0xD56041E4 }
+_tbl[35] = { 0xA2677172 }
+_tbl[36] = { 0x3C03E4D1 }
+_tbl[37] = { 0x4B04D447 }
+_tbl[38] = { 0xD20D85FD }
+_tbl[39] = { 0xA50AB56B }
+_tbl[40] = { 0x35B5A8FA }
+_tbl[41] = { 0x42B2986C }
+_tbl[42] = { 0xDBBBC9D6 }
+_tbl[43] = { 0xACBCF940 }
+_tbl[44] = { 0x32D86CE3 }
+_tbl[45] = { 0x45DF5C75 }
+_tbl[46] = { 0xDCD60DCF }
+_tbl[47] = { 0xABD13D59 }
+_tbl[48] = { 0x26D930AC }
+_tbl[49] = { 0x51DE003A }
+_tbl[50] = { 0xC8D75180 }
+_tbl[51] = { 0xBFD06116 }
+_tbl[52] = { 0x21B4F4B5 }
+_tbl[53] = { 0x56B3C423 }
+_tbl[54] = { 0xCFBA9599 }
+_tbl[55] = { 0xB8BDA50F }
+_tbl[56] = { 0x2802B89E }
+_tbl[57] = { 0x5F058808 }
+_tbl[58] = { 0xC60CD9B2 }
+_tbl[59] = { 0xB10BE924 }
+_tbl[60] = { 0x2F6F7C87 }
+_tbl[61] = { 0x58684C11 }
+_tbl[62] = { 0xC1611DAB }
+_tbl[63] = { 0xB6662D3D }
+_tbl[64] = { 0x76DC4190 }
+_tbl[65] = { 0x1DB7106 }
+_tbl[66] = { 0x98D220BC }
+_tbl[67] = { 0xEFD5102A }
+_tbl[68] = { 0x71B18589 }
+_tbl[69] = { 0x6B6B51F }
+_tbl[70] = { 0x9FBFE4A5 }
+_tbl[71] = { 0xE8B8D433 }
+_tbl[72] = { 0x7807C9A2 }
+_tbl[73] = { 0xF00F934 }
+_tbl[74] = { 0x9609A88E }
+_tbl[75] = { 0xE10E9818 }
+_tbl[76] = { 0x7F6A0DBB }
+_tbl[77] = { 0x86D3D2D }
+_tbl[78] = { 0x91646C97 }
+_tbl[79] = { 0xE6635C01 }
+_tbl[80] = { 0x6B6B51F4 }
+_tbl[81] = { 0x1C6C6162 }
+_tbl[82] = { 0x856530D8 }
+_tbl[83] = { 0xF262004E }
+_tbl[84] = { 0x6C0695ED }
+_tbl[85] = { 0x1B01A57B }
+_tbl[86] = { 0x8208F4C1 }
+_tbl[87] = { 0xF50FC457 }
+_tbl[88] = { 0x65B0D9C6 }
+_tbl[89] = { 0x12B7E950 }
+_tbl[90] = { 0x8BBEB8EA }
+_tbl[91] = { 0xFCB9887C }
+_tbl[92] = { 0x62DD1DDF }
+_tbl[93] = { 0x15DA2D49 }
+_tbl[94] = { 0x8CD37CF3 }
+_tbl[95] = { 0xFBD44C65 }
+_tbl[96] = { 0x4DB26158 }
+_tbl[97] = { 0x3AB551CE }
+_tbl[98] = { 0xA3BC0074 }
+_tbl[99] = { 0xD4BB30E2 }
+_tbl[100] = { 0x4ADFA541 }
+_tbl[101] = { 0x3DD895D7 }
+_tbl[102] = { 0xA4D1C46D }
+_tbl[103] = { 0xD3D6F4FB }
+_tbl[104] = { 0x4369E96A }
+_tbl[105] = { 0x346ED9FC }
+_tbl[106] = { 0xAD678846 }
+_tbl[107] = { 0xDA60B8D0 }
+_tbl[108] = { 0x44042D73 }
+_tbl[109] = { 0x33031DE5 }
+_tbl[110] = { 0xAA0A4C5F }
+_tbl[111] = { 0xDD0D7CC9 }
+_tbl[112] = { 0x5005713C }
+_tbl[113] = { 0x270241AA }
+_tbl[114] = { 0xBE0B1010 }
+_tbl[115] = { 0xC90C2086 }
+_tbl[116] = { 0x5768B525 }
+_tbl[117] = { 0x206F85B3 }
+_tbl[118] = { 0xB966D409 }
+_tbl[119] = { 0xCE61E49F }
+_tbl[120] = { 0x5EDEF90E }
+_tbl[121] = { 0x29D9C998 }
+_tbl[122] = { 0xB0D09822 }
+_tbl[123] = { 0xC7D7A8B4 }
+_tbl[124] = { 0x59B33D17 }
+_tbl[125] = { 0x2EB40D81 }
+_tbl[126] = { 0xB7BD5C3B }
+_tbl[127] = { 0xC0BA6CAD }
+_tbl[128] = { 0xEDB88320 }
+_tbl[129] = { 0x9ABFB3B6 }
+_tbl[130] = { 0x3B6E20C }
+_tbl[131] = { 0x74B1D29A }
+_tbl[132] = { 0xEAD54739 }
+_tbl[133] = { 0x9DD277AF }
+_tbl[134] = { 0x4DB2615 }
+_tbl[135] = { 0x73DC1683 }
+_tbl[136] = { 0xE3630B12 }
+_tbl[137] = { 0x94643B84 }
+_tbl[138] = { 0xD6D6A3E }
+_tbl[139] = { 0x7A6A5AA8 }
+_tbl[140] = { 0xE40ECF0B }
+_tbl[141] = { 0x9309FF9D }
+_tbl[142] = { 0xA00AE27 }
+_tbl[143] = { 0x7D079EB1 }
+_tbl[144] = { 0xF00F9344 }
+_tbl[145] = { 0x8708A3D2 }
+_tbl[146] = { 0x1E01F268 }
+_tbl[147] = { 0x6906C2FE }
+_tbl[148] = { 0xF762575D }
+_tbl[149] = { 0x806567CB }
+_tbl[150] = { 0x196C3671 }
+_tbl[151] = { 0x6E6B06E7 }
+_tbl[152] = { 0xFED41B76 }
+_tbl[153] = { 0x89D32BE0 }
+_tbl[154] = { 0x10DA7A5A }
+_tbl[155] = { 0x67DD4ACC }
+_tbl[156] = { 0xF9B9DF6F }
+_tbl[157] = { 0x8EBEEFF9 }
+_tbl[158] = { 0x17B7BE43 }
+_tbl[159] = { 0x60B08ED5 }
+_tbl[160] = { 0xD6D6A3E8 }
+_tbl[161] = { 0xA1D1937E }
+_tbl[162] = { 0x38D8C2C4 }
+_tbl[163] = { 0x4FDFF252 }
+_tbl[164] = { 0xD1BB67F1 }
+_tbl[165] = { 0xA6BC5767 }
+_tbl[166] = { 0x3FB506DD }
+_tbl[167] = { 0x48B2364B }
+_tbl[168] = { 0xD80D2BDA }
+_tbl[169] = { 0xAF0A1B4C }
+_tbl[170] = { 0x36034AF6 }
+_tbl[171] = { 0x41047A60 }
+_tbl[172] = { 0xDF60EFC3 }
+_tbl[173] = { 0xA867DF55 }
+_tbl[174] = { 0x316E8EEF }
+_tbl[175] = { 0x4669BE79 }
+_tbl[176] = { 0xCB61B38C }
+_tbl[177] = { 0xBC66831A }
+_tbl[178] = { 0x256FD2A0 }
+_tbl[179] = { 0x5268E236 }
+_tbl[180] = { 0xCC0C7795 }
+_tbl[181] = { 0xBB0B4703 }
+_tbl[182] = { 0x220216B9 }
+_tbl[183] = { 0x5505262F }
+_tbl[184] = { 0xC5BA3BBE }
+_tbl[185] = { 0xB2BD0B28 }
+_tbl[186] = { 0x2BB45A92 }
+_tbl[187] = { 0x5CB36A04 }
+_tbl[188] = { 0xC2D7FFA7 }
+_tbl[189] = { 0xB5D0CF31 }
+_tbl[190] = { 0x2CD99E8B }
+_tbl[191] = { 0x5BDEAE1D }
+_tbl[192] = { 0x9B64C2B0 }
+_tbl[193] = { 0xEC63F226 }
+_tbl[194] = { 0x756AA39C }
+_tbl[195] = { 0x26D930A }
+_tbl[196] = { 0x9C0906A9 }
+_tbl[197] = { 0xEB0E363F }
+_tbl[198] = { 0x72076785 }
+_tbl[199] = { 0x5005713 }
+_tbl[200] = { 0x95BF4A82 }
+_tbl[201] = { 0xE2B87A14 }
+_tbl[202] = { 0x7BB12BAE }
+_tbl[203] = { 0xCB61B38 }
+_tbl[204] = { 0x92D28E9B }
+_tbl[205] = { 0xE5D5BE0D }
+_tbl[206] = { 0x7CDCEFB7 }
+_tbl[207] = { 0xBDBDF21 }
+_tbl[208] = { 0x86D3D2D4 }
+_tbl[209] = { 0xF1D4E242 }
+_tbl[210] = { 0x68DDB3F8 }
+_tbl[211] = { 0x1FDA836E }
+_tbl[212] = { 0x81BE16CD }
+_tbl[213] = { 0xF6B9265B }
+_tbl[214] = { 0x6FB077E1 }
+_tbl[215] = { 0x18B74777 }
+_tbl[216] = { 0x88085AE6 }
+_tbl[217] = { 0xFF0F6A70 }
+_tbl[218] = { 0x66063BCA }
+_tbl[219] = { 0x11010B5C }
+_tbl[220] = { 0x8F659EFF }
+_tbl[221] = { 0xF862AE69 }
+_tbl[222] = { 0x616BFFD3 }
+_tbl[223] = { 0x166CCF45 }
+_tbl[224] = { 0xA00AE278 }
+_tbl[225] = { 0xD70DD2EE }
+_tbl[226] = { 0x4E048354 }
+_tbl[227] = { 0x3903B3C2 }
+_tbl[228] = { 0xA7672661 }
+_tbl[229] = { 0xD06016F7 }
+_tbl[230] = { 0x4969474D }
+_tbl[231] = { 0x3E6E77DB }
+_tbl[232] = { 0xAED16A4A }
+_tbl[233] = { 0xD9D65ADC }
+_tbl[234] = { 0x40DF0B66 }
+_tbl[235] = { 0x37D83BF0 }
+_tbl[236] = { 0xA9BCAE53 }
+_tbl[237] = { 0xDEBB9EC5 }
+_tbl[238] = { 0x47B2CF7F }
+_tbl[239] = { 0x30B5FFE9 }
+_tbl[240] = { 0xBDBDF21C }
+_tbl[241] = { 0xCABAC28A }
+_tbl[242] = { 0x53B39330 }
+_tbl[243] = { 0x24B4A3A6 }
+_tbl[244] = { 0xBAD03605 }
+_tbl[245] = { 0xCDD70693 }
+_tbl[246] = { 0x54DE5729 }
+_tbl[247] = { 0x23D967BF }
+_tbl[248] = { 0xB3667A2E }
+_tbl[249] = { 0xC4614AB8 }
+_tbl[250] = { 0x5D681B02 }
+_tbl[251] = { 0x2A6F2B94 }
+_tbl[252] = { 0xB40BBE37 }
+_tbl[253] = { 0xC30C8EA1 }
+_tbl[254] = { 0x5A05DF1B }
+_tbl[255] = { 0x2D02EF8D }
+
+
+       -- Calculate it
+       local ret = 0
+       for i,item in pairs(data) do
+               local tmp =  band(ret, 0xFF)
+               local index = band( bxor(tmp, item), 0xFF)
+               ret = bxor(rshift(ret,8), _tbl[index][1])
+       end
+       return ret
+end
+---
+-- update checksum
+-- called: data is string, ( >= 24 hex digits )
+-- returns: string, (data concat new checksum)
+local function updateChecksum(data)
+       local part = data:sub(1,24)
+       local chksum = calculateChecksum( utils.ConvertHexToBytes(part))        
+       return string.format("%s%X", part, chksum)
+end
+---
+-- receives the answer from deviceside, used with a readblock command
+local function waitCmd()
+       local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)
+       if response then
+               local count,cmd,arg0 = bin.unpack('LL',response)
+               if(arg0==1) then
+                       local count,arg1,arg2,data = bin.unpack('LLH511',response,count)
+                       return data:sub(1,32)
+               else
+                       return nil, "Couldn't read block.." 
+               end
+       end
+       return nil, "No response from device"
+end
+
+local function selftest()
+       local testdata = '000F42430D0A14000001D11F'..'5D738517'
+       local chksum = getChecksum(testdata)
+       local calc = calculateChecksum( utils.ConvertHexToBytes(testdata:sub(1,24)))    
+       print  ('TESTDATA    :: '..testdata)
+       print  ('DATA        :: '..testdata:sub(1,24))
+       print (('CHKSUM      :: %X'):format(chksum))    
+       print (('CHKSUM CALC :: %X'):format(calc))      
+       print ('UPDATE CHKSUM :: '..updateChecksum(testdata))
+       
+       
+end
+--- 
+-- The main entry point
+-- -d decrypt
+-- -e encrypt
+-- -v validate
+function main(args)
+
+       local cmd, result, err, blockNo, keyA
+       local blocks = {}
+       local decryptkey = ''
+       
+       -- Read the parameters
+       for o, a in getopt.getopt(args, 'hk:') do
+               if o == "h" then help() return end
+               if o == "k" then keyA = a end
+       end
+       
+       selftest()
+       
+       local tst2 = '00100100030209094312356432324E34B79A349B'
+       
+       -- validate input args.
+       keyA =  keyA or '6dd747e86975'
+       if #(keyA) ~= 12 then
+               return oops( string.format('Wrong length of write key (was %d) expected 12', #keyA))
+       end
+       
+       -- Turn off Debug
+       local cmdSetDbgOff = "hf mf dbg 0"
+       core.console( cmdSetDbgOff) 
+
+       -- GET TAG UID
+       
+       result, err = lib14a.read1443a(false)
+       if not result then
+               return oops(err)
+       end
+
+       core.clearCommandBuffer()
+
+       print(result.uid, keyA)
+
+       local my = result.uid
+       if 1 == 1 then 
+               return
+       end
+       
+       -- Show tag info
+       print((' Found tag %s'):format(result.name))
+       
+       local longrandom = RANDOM..result.uid
+       local res = utils.Sha1Hex(longrandom)
+       res  = utils.ConvertBytesToHex(utils.ConvertAsciiToBytes(res:sub(1,16)))
+       decryptkey = utils.SwapEndiannessStr(res:sub(1,8) , 32)
+       decryptkey = decryptkey..utils.SwapEndiannessStr( res:sub(9,16),32)
+       decryptkey = decryptkey..utils.SwapEndiannessStr( res:sub(17,24),32)
+       decryptkey = decryptkey..utils.SwapEndiannessStr( res:sub(25,32),32)
+       print('Decrypt key::',decryptkey)
+       print('Reading card data')
+       print('Raw','Decrypted')
+       for blockNo = 0, numBlocks-1, 1 do
+
+               if core.ukbhit() then
+                       print("aborted by user")
+                       break
+               end
+
+               cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = blockNo ,arg2 = 0,arg3 = 0, data = keyA}
+               local err = core.SendCommand(cmd:getBytes())
+               if err then return oops(err) end
+               local blockdata, err = waitCmd()
+               if err then return oops(err) end        
+                       
+               if  blockNo%4 ~= 3 then
+                       
+                       -- blocks with zero not encrypted.
+                       if string.find(blockdata, '^0+$') then
+                               print(blockdata, blockdata)
+                       else
+                               local aes = core.aes128_decrypt_ecb(decryptkey, blockdata)
+                               local bytes =  utils.ConvertAsciiToBytes(aes)
+                               local hex = utils.ConvertBytesToHex(bytes)
+                               print(blockdata , hex)
+                       end
+               elseif blockNo == 0 then
+                       print(blockdata,blockdata)
+               else
+                       -- Sectorblocks, not encrypted
+                       local sectortrailer = keyA..blockdata:sub(13,20)..keyA
+                       print(sectortrailer, sectortrailer, blockdata:sub(13,20))
+               end
+       end
+       -- checksum fyra sista bytes i varje rad.  (kanske inte för s0)
+       -- s0b1,s1b0,s2b0,s3b0
+       -- 
+end
+
+main(args)
index 973cd103c009b16697b7523b1cbf60b107500f7a..a37f1d7e35f69e63e6fba2259f0a011b8f1bf4ec 100644 (file)
@@ -8,38 +8,54 @@
 
 #include "crc16.h"
 
-
 unsigned short update_crc16( unsigned short crc, unsigned char c )
 {
-  unsigned short i, v, tcrc = 0;
+       unsigned short i, v, tcrc = 0;
 
-  v = (crc ^ c) & 0xff;
-  for (i = 0; i < 8; i++) {
-      tcrc = ( (tcrc ^ v) & 1 ) ? ( tcrc >> 1 ) ^ 0x8408 : tcrc >> 1;
-      v >>= 1;
-  }
+       v = (crc ^ c) & 0xff;
+       for (i = 0; i < 8; i++) {
+               tcrc = ( (tcrc ^ v) & 1 ) ? ( tcrc >> 1 ) ^ 0x8408 : tcrc >> 1;
+               v >>= 1;
+       }
 
-  return ((crc >> 8) ^ tcrc)&0xffff;
+       return ((crc >> 8) ^ tcrc)&0xffff;
 }
 
 uint16_t crc16(uint8_t const *message, int length, uint16_t remainder, uint16_t polynomial) {
-    
-       if (length == 0)
-        return (~remainder);
-                       
-    for (int byte = 0; byte < length; ++byte) {
-        remainder ^= (message[byte] << 8);
-        for (uint8_t bit = 8; bit > 0; --bit) {
-            if (remainder & 0x8000) {
-                remainder = (remainder << 1) ^ polynomial;
-            } else {
-                remainder = (remainder << 1);
-            }
-        }
-    }
-    return remainder;
+
+       if (length == 0) return (~remainder);
+
+       for (int byte = 0; byte < length; ++byte) {
+               remainder ^= (message[byte] << 8);
+               for (uint8_t bit = 8; bit > 0; --bit) {
+                       if (remainder & 0x8000) {
+                               remainder = (remainder << 1) ^ polynomial;
+                       } else {
+                               remainder = (remainder << 1);
+                       }
+               }
+       }
+       return remainder;
 }
 
 uint16_t crc16_ccitt(uint8_t const *message, int length) {
-    return crc16(message, length, 0xffff, 0x1021);
+       return crc16(message, length, 0xffff, 0x1021);
+}
+
+uint16_t crc16_ccitt_kermit(uint8_t const *message, int length) {
+       return bit_reverse_uint16(crc16(message, length, 0x0000, 0x1021));
+}
+
+uint16_t bit_reverse_uint16 (uint16_t value) {
+       const uint16_t mask0 = 0x5555;
+       const uint16_t mask1 = 0x3333;
+       const uint16_t mask2 = 0x0F0F;
+       const uint16_t mask3 = 0x00FF;
+
+       value = (((~mask0) & value) >> 1) | ((mask0 & value) << 1);
+       value = (((~mask1) & value) >> 2) | ((mask1 & value) << 2);
+       value = (((~mask2) & value) >> 4) | ((mask2 & value) << 4);
+       value = (((~mask3) & value) >> 8) | ((mask3 & value) << 8);
+
+       return value;
 }
index d16d83b5afdb162c088e35e4a01aee33e2760e3d..8eb4befbcf1d7566cf0d7f8f73c370f29080e0ba 100644 (file)
@@ -12,4 +12,6 @@
 unsigned short update_crc16(unsigned short crc, unsigned char c);
 uint16_t crc16(uint8_t const *message, int length, uint16_t remainder, uint16_t polynomial);
 uint16_t crc16_ccitt(uint8_t const *message, int length);
+uint16_t crc16_ccitt_kermit(uint8_t const *message, int length);
+uint16_t bit_reverse_uint16 (uint16_t value);
 #endif
index 7d40d22e5aa44551835ae4ada1f69947f132e488..f13a567c6fe8cda87b1cf70248cd201603fe023f 100644 (file)
@@ -526,7 +526,7 @@ int ParadoxdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, ui
        return (int)startIdx;
 }
 
-uint32_t bytebits_to_byte(uint8_tsrc, size_t numbits)
+uint32_t bytebits_to_byte(uint8_t *src, size_t numbits)
 {
        uint32_t num = 0;
        for(int i = 0 ; i < numbits ; i++)
@@ -537,6 +537,17 @@ uint32_t bytebits_to_byte(uint8_t* src, size_t numbits)
        return num;
 }
 
+//least significant bit first
+uint32_t bytebits_to_byteLSBF(uint8_t *src, size_t numbits)
+{
+       uint32_t num = 0;
+       for(int i = 0 ; i < numbits ; i++)
+       {
+               num = (num << 1) | *(src + (numbits-(i+1)));
+       }
+       return num;
+}
+
 int IOdemodFSK(uint8_t *dest, size_t size)
 {
        if (justNoise(dest, size)) return -1;
@@ -569,7 +580,7 @@ int IOdemodFSK(uint8_t *dest, size_t size)
 
 // by marshmellow
 // takes a array of binary values, start position, length of bits per parity (includes parity bit),
-//   Parity Type (1 for odd 0 for even), and binary Length (length to run) 
+//   Parity Type (1 for odd; 0 for even; 2 for just drop it), and binary Length (length to run) 
 size_t removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t pType, size_t bLen)
 {
        uint32_t parityWd = 0;
@@ -581,7 +592,9 @@ size_t removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t p
                }
                j--;
                // if parity fails then return 0
-               if (parityTest(parityWd, pLen, pType) == 0) return -1;
+               if (pType != 2) {
+                       if (parityTest(parityWd, pLen, pType) == 0) return -1;
+               }
                bitCnt+=(pLen-1);
                parityWd = 0;
        }
@@ -590,6 +603,21 @@ size_t removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t p
        return bitCnt;
 }
 
+// Ask/Biphase Demod then try to locate an ISO 11784/85 ID
+// BitStream must contain previously askrawdemod and biphasedemoded data
+int FDXBdemodBI(uint8_t *dest, size_t *size)
+{
+       //make sure buffer has enough data
+       if (*size < 128) return -1;
+
+       size_t startIdx = 0;
+       uint8_t preamble[] = {0,0,0,0,0,0,0,0,0,0,1};
+
+       uint8_t errChk = preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx);
+       if (errChk == 0) return -2; //preamble not found
+       return (int)startIdx;
+}
+
 // by marshmellow
 // FSK Demod then try to locate an AWID ID
 int AWIDdemodFSK(uint8_t *dest, size_t *size)
index ab81c34c459ef327cbe3ea595af3f1ecf1d5a72b..d16aab9eb4205ff1f34a1438411ad04bc1f0820e 100644 (file)
@@ -19,6 +19,7 @@
 int      askdemod(uint8_t *BinStream, size_t *size, int *clk, int *invert, int maxErr, uint8_t amp, uint8_t askType);
 int      BiphaseRawDecode(uint8_t * BitStream, size_t *size, int offset, int invert);
 uint32_t bytebits_to_byte(uint8_t* src, size_t numbits);
+uint32_t bytebits_to_byteLSBF(uint8_t* src, size_t numbits);
 uint16_t countFC(uint8_t *BitStream, size_t size, uint8_t fskAdj);
 int      DetectASKClock(uint8_t dest[], size_t size, int *clock, int maxErr);
 uint8_t  DetectCleanAskWave(uint8_t dest[], size_t size, uint8_t high, uint8_t low);
@@ -40,6 +41,7 @@ void     psk1TOpsk2(uint8_t *BitStream, size_t size);
 size_t   removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t pType, size_t bLen);
 
 //tag specific
+int FDXBdemodBI(uint8_t *dest, size_t *size);
 int AWIDdemodFSK(uint8_t *dest, size_t *size);
 int gProxII_Demod(uint8_t BitStream[], size_t *size);
 int HIDdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo);
index 6a4c9a103bff1a03ebb21215e968b54bc9aa7f09..aa80491b58f2b94d61313e01e1b4b4a2f64ac6a5 100644 (file)
@@ -1,4 +1,3 @@
-#include <stdio.h>
 #include <strings.h>
 #include <string.h>
 #include <stdint.h>
Impressum, Datenschutz